SQL Server OLE DB Command Param order (SSIS)

dgenwo3n  于 2023-10-15  发布在  其他
关注(0)|答案(1)|浏览(82)

What exactly determines the order of the Parameters in a OLE DB Command (SSIS). For example, I have a table looks as follows.

CREATE TABLE [dbo].[DimAppointmentFlags] (
  [RowIdentifier] bigint PRIMARY KEY,
  [AppointmentID] bigint,
  [Flag] varchar(255)
)
GO

and the statement I am running in the command in SSIS is:

UPDATE [dbo].[DimAppointmentFlags]
SET [AppointmentID] = ?,
[Flag] = ?
WHERE [RowIdentifier] = ?

My first assumption was that they where in field order i.e.

RowIdentifier is Param_0 AppointmentID is Param_1 Flag is Param_2

I can see that this is not the case though. Can some elaborate on this as I find the official documentation to be not that helpful:

https://learn.microsoft.com/en-us/sql/integration-services/data-flow/transformations/ole-db-command-transformation?view=sql-server-ver16

qyswt5oh

qyswt5oh1#

OLE DB Connection managers and ODBC Connection managers use an ordinal based token replacement system. The token is ? . The difference is OLE DB uses a zero based counting system whereas ODBC uses a one based.

In your example

SET [AppointmentID] = ?,
[Flag] = ?
WHERE [RowIdentifier] = ?

The first question mark, for AppointmentID, correlates to the Param_0 (or just 0 in the Execute SQL, OLE DB Source or Lookup component) value.

The second, Flag, will correlate to Param_1, etc.

Let's take a slightly different variation on your query. Instead of just updating where the row identifier is some value, let's also only update it when the Appointment Id is also a given value. This is a situation where the ordinal based system gets silly.

SET [AppointmentID] = ?,
[Flag] = ?
WHERE [RowIdentifier] = ?
-- ADDED THIS PART
AND [AppointmentID] = ?

The first AppointmentID is ordinal zero. Flat is ordinal one, RowIdentifier is ordinal two and the last ApppointmentID is ordinal three. Even though the "same" value is being used in both places, it's a "dumb" system where it's literally replace every token exactly once.

For completeness, ADO Connection Managers use Named parameters so it would look something like

SET [AppointmentID] = @apptid,
[Flag] = @flag
WHERE [RowIdentifier] = @rowident
-- ADDED THIS PART
AND [AppointmentID] = @apptid;

Here we can see that we only have 3 parameters to populate as we reuse @apptid.

Finally, in Execute SQL Commands and I think OLE DB Source (definitely not OLE DB Command or a Lookup), you can get the best of both worlds if you find yourself needing to reference a parameter multiple times in a query by declaring SQL variables and populating them from the parameters.

DECLARE @apptid int = ?
,   @flag bit = ?
,   @rowident int = ?;

SET [AppointmentID] = @apptid,
[Flag] = @flag
WHERE [RowIdentifier] = @rowident
-- ADDED THIS PART
AND [AppointmentID] = @apptid;

Now we have 3 parameters OLE/ODBC can map in exactly once but we can reuse them as needed in the body of our query. And as a bonus, it's easy to copy that into your query tool and test.

相关问题