I have an SSIS data flow task where I am trying to load data from a source table using ADO.NET Source Editor into a SQL Server table.
The problem:
The source table name is dynamic and depends on the current date.
Example: If I want to load today's data then the table name would be Sample_03292017_data and if loading tomorrow's data then it would be Sample_03302017_Data.
I did some research and found how to pass parameters to an ADO.NET Source Editor to use in where conditions but I couldn't find anything on how to use this parameter in a table name.
Does anyone know how I can achieve this? My query is really simple:
select * from Sample_[DateParameter]_Data.
I am using Visual Studio Data Tools 2010.
Expression must be set on the Data Flow Task not in the Ado.net Source
Follow this steps to set an expression for an Ado.net Source:
in the control flow tab click on the Data Flow Task and press F4 to show the properties tab
Click on the expression button, it show up a form like shown below
choose [Ado.net Source].sqlcommand property and click on the expression builder button
write the following expression "select * from Sample_ " + #[User::DateParameter] + "_Data" (assuming that your data parameter is stored in a variable named DateParameter)
You should use dynamic SQL to achieve this. If you are using ADO.net as Connection Type, copy and paste the following to your SQL statement:
Declare #SQL VARCHAR(MAX)
SET #SQL = 'Select * from ' + #TABLE
EXEC(#SQL)
In the parameter page, you need to Add new parameter which has #TABLE as the parameter name and leave the size as -1. The #Table variable should be decided by the expression from variable setting page.
Related
I have created a variable in ssis called Vpop_summary_table.
I have used this variable in a sql statement.
my variable
Vpop_summary_table
is expected to give value
[dbo].[2019-02-02_pop_table]
It is fine in ssis.
DECLARE #Vpop_summary_table VARCHAR(100)
SET #Vpop_summary_table= ?
SELECT
,[Age Range]
,[Gender]
,[2023 Population]
INTO [#Vpop_summary_table]
FROM [dbo].[2018_Population_Table_CLARITAS]
My table is created as [#Vpop_summary_table] instead of [dbo].[2019-02-02_pop_table]
Table names and column names need to be static.
If you want to do this create the full SQL and then use sp_executesql to execute it although in terms of good practices having a table in a variable doesn't look so great...
You cannot pass table name as parameter, you have to use expressions to achieve that:
Open Execute SQL Task editor, Go To Expressions Tab, add an expression for the SQLStatementSource property as following:
"SELECT
[Age Range]
,[Gender]
,[2023 Population]
INTO " + #[User::Vpop_summary_table] + "
FROM [dbo].[2018_Population_Table_CLARITAS]"
More info at:
Common Examples of SSIS Expressions and Variables (check Working with SSIS expressions section)
I have a data flow working just fine, it is compound of a source that is evaluated by a lookup component and then it does an upsert, diagram is shown here:
Now, on BanqueCIBI (the ole db source), I have a SQL Command Text where I would like to receive a param from another component to use it as valueDate. This is the query right now:
SELECT [IdTransactionType]
,[IdBank]
,[IdBanqueDetailHistoryRef]
,[IdBanqueDetail]
,[IdBanqueHeader]
,[CCI]
,[ValueDate]
,[Text]
,[Reference]
,[Amount]
,[Sign]
,[IdCurrency]
,[OrigBranch]
,[dtCreatedOrModified]
,[oldText]
,[oldReference]
,[IdAccount]
,[IdSubAccount]
,[Date]
,[IdRD]
,[Flag]
,[History]
,[DtDate]
,[iTIB]
,[iSAP]
FROM [dbCibi3].[dbo].[BanqueDetailHistoryRef]
WHERE [ValueDate] = '2015-31-01'
So, the diagram would look something like this:
Right now, that new OLE DB Command looks like this:
And this is the usp_GetDateParamsSSIS invoked in the source above:
USE [dbMODIFE]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[usp_GetDateParamSSIS]
#name VARCHAR(50) = NULL,
#value DATETIME OUTPUT
AS
BEGIN
SELECT TOP 1 #value =valueDate FROM helperPARAMS_SSIS WHERE name = #name;
END
So, how could I use that #value OUTPUT on the BanqueCIBI component? Thank you so much! (Please notice that BanqueCibi and the new component are querying different servers and a linked served is not an option because of company's policies).
Ok, since you are passing a hard-coded Name parameter to your stored procedure, I am assuming that this is a stored procedure you only need to call once for each execution of the package, and not something you're calling once for every row in your data source.
In that case, do NOT call the stored proc with an OLE DB Command in the data flow.
Instead, call it with an Execute SQL Task that you put BEFORE the DataFlow Task in the Command Flow. Direct the return value of the proc to a package-level variable.
Then in the Source of your dataflow (BanqueCIBI), map that variable to the first parameter of your SELECT query.
There are examples of all of these techniques easily available on the internet. But if you find one you are having trouble following, feel free to edit your question with the details, or create a new question if it is sufficiently different in scope from this one.
I am trying to run the SQL Transport Schema Generation Wizard against a SQL 2012 server. The stored procedure has a datetime parameter. If i simply put in a date like 12/26/2013 05:00:00 Am, then the "Generate" button doesn't show an argument. If i try putting the date/time in a single quote or using a string like 2013-12-26T05:00:00.000, the parameter is generated, but i get the following error when i try to execute. "Failed to execute SQL Statement. Please ensure that the supplied syntax is correct. "
I got to this point by creating a SQL Query that output it's response using FOR XML AUTO, ELEMENTS in it. I then open my BizTalk solution in VS 2012, Go to "Add Items -> Add Generated Items". Select Add Adapter Metadata. From there, it asks the location of the message box. I use my local server. It then asks for the connection string for the SQL Server with the stored procedure. I enter that (it's the same as the server with the message box). I specify the namespace and the root element name for the document. This is set as a receive port. I next select stored procedure and move to the next screen. I then select the stored proc from a drop down list. Below, in a grid, i am shown the parameters for the stored proc. Here is where i am having trouble. I cannot seem to get it to accept the datetime argument no matter what i put in here.
Is there something i am doing wrong?
It is better to do the following steps and to use the new WCF-SQL rather than the old deprecated SQL adapter.
Add Items
Add Generated Items
Consume Adapter Service
Select sqlBinding and Configure the URI
Click Connect
Select Client (Outbound operations)
Select Strongly-Type Procedures
Select the Stored Procedure from Available categories and operations
Click Add
Give it a Filename Prefix
Click OK
This will generated the schemas plus binding files to create the port.
You also don't need to have the FOR XML AUTO, ELEMENTS in your stored procedure any more.
I have a simple task but somehow getting bugged on it.
Through SSIS I want to empty 3 tables in my database. I'm using SQL Server 2008 R2.
I want to create a FEL and somwehere in the variable put the names of my two tables.
Then the loop will go and delete records from those two tables.
Tables are: Table1 Table2 and Table3.
Can you please give me a detailed step by step isntruction. Please don't paste links to other articles, as it might be even more confusing.
Thank you very much!
Create a variable named TableNames of type Object
Create a variable named TableName of type String
Create a variable named Query of type String
Set the EvaluateAsExpression property to True
Set the Expression property to "DELETE FROM " + #[User::TableName]
Add an Execute Sql Task and double click to open the Execute Sql Task Editor
Make the following changes under the General settings
Set the ResultSet property to Full Result Set
Set the SQLStatement property to
select *
from
(
select 'Table1' as t union
select 'Table2' as t union
select 'Table3' as t
) tables
Make the following changes under the Result Set settings
Click Add button, and set the Result Name to 0 and the Variable Name to User::TableNames
Add a Foreach Loop Container and double click to open the Foreach Loop Editor
Make the following changes under the Collection settings
Set the Enumerator property to Foreach ADO Enumerator
Set the ADO object source variable to User::TableNames
Make the following changes under the Variable Mappings settings
Set the Variable to User::TableName and the Index to 0
Add an Execute Sql Task inside the Foreach Loop and double click to open the Execute Sql Task Editor
Make the following changes under the General settings
Set the SQLSourceType property to Variable
Set the SourceVariable to User::Query
I have a stored procedure that gets executed through SQL SSIS using a Execute SQL Task.
The task has the following:
USE [OPPY_DWUSD]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[generate_merge_scdbk]
#Schema = N'dim',
#Dimension = N'VARIETY',
#ETLSchema = N'stg',
#ETLTable = N'vw_VARIETY',
#Execute = 1
SELECT 'Return Value' = #return_value
GO
Right now the way I have this setup, I have multiple Execute SQL Tasks with the same code but different values, about 20 Execute SQL Tasks.
Is there a more cleaner way to pull this off?
Here is one way of doing this. The example uses SSIS 2008 R2 with SQL Server 2012 backend.
Create a table to store your parameter values. Let's say the table name is dbo.SProcValues. Based on your stored procedure definition, the table schema would look like this.
CREATE TABLE dbo.SProcValues(
Id int IDENTITY(1,1) NOT NULL,
SProcName nvarchar(40) NOT NULL,
SchemaName nvarchar(20) NOT NULL,
Dimension nvarchar(40) NOT NULL,
ETLSchema nvarchar(20) NOT NULL,
ETLTable nvarchar(40) NOT NULL,
IsExecute bit NOT NULL
)
GO
Let's insert some sample data using the following script.
INSERT INTO dbo.SProcValues
(SProcName, SchemaName, Dimension, ETLSchema, ETLTable, IsExecute) VALUES
('dbo.sp_generate_merge', 'dim1', 'dimension1', 'stg1', 'table1', 1),
('dbo.sp_generate_merge_scdbk', 'dim2', 'dimension2', 'stg2', 'table2', 1),
('dbo.sp_generate_merge_scdbk', 'dim3', 'dimension3', 'stg3', 'table3', 0),
('dbo.sp_generate_merge', 'dim4', 'dimension4', 'stg4', 'table4', 0);
GO
On the SSIS package, assuming that you have the data source and connection manager already established. Create the following variables. Variable SProcValues will hold the parameter set that we stored in the above-mentioned table. Variable SQLInnerQuery will hold the query that will be used later in the inner Execute SQL Task. Other variables relate to each column available in the table so we can loop through each row and hold it in a variable.
Paste the following query in the value of the variable SQLGetParameters
SELECT SProcName, SchemaName, Dimension, ETLSchema, ETLTable, IsExecute FROM dbo.SProcValues
Select the variable SQLInnerQuery and press F4 to view the properties. Set the property EvaluateAsExpression to True and then click the Ellipsis button against the Expression property.
We need to set an expression that will evaluate to the EXEC stored procedure statement that can be later supplied to the inner Execute SQL Task. Set the following expression.
"EXEC " + #[User::SProcName] + " #Schema = ?, #Dimension = ?, #ETLSchema = ?, #ETLTable = ?, #IsExecute = ?"
If you click Evaluate Expression button on the editor, you can see what the expression will evaluate to. You will also notice that there is no stored procedure name in the below screenshot that is because the package variable SProcName currently does not have any value. During runtime, the SProcName will be assigned with the value from the table and this expression will automatically resolve itself.
On the SSIS package, drag and drop an Execute SQL Task. This task will run the following query to fetch the list of parameter values that are stored in the table dbo.SProcValues. Configure the General page on the Execute SQL Task as shown below. The example uses OLEDB connection and the connection manager/data source is named as Practice.
Configure the Result Set page of Execute SQL Task to store the result set from the query to an object variable.
Now that the first Execute SQL Task is configured to get the list of parameter values that should be passed to the stored procedure, you need to loop through the records.
Drag and drop a Foreach Loop container. Connect the Execute SQL Task's precedence container to the Foreach Loop container. Configure the Collection page of the Foreach Loop container as shown below. We are looping through the result set using the ADO enumerator.
Configure the Variable Mappings page on Foreach Loop container as shown below. As we loop through each row, we are storing the column values in respective variables so we can pass it to the next Execute SQL Task to run the stored procedure.
Drag and drop an Execute SQL Task inside the Foreach Loop container so that this task is executed each time we loop through a row in the result set. Configure the Execute SQL Task as shown below.
NOTE
You might want to configure the ResultSet property on this second Execute SQL Task according to your requirements. If you choose ResultSet, then you need to configure an appropriate object variable to accept the result set. I left it as None for this example.
Configure the values to be passed as parameters to the stored procedure.
Finally, the control flow would look something like this.
When the package runs, the loop will execute the stored procedure for as many records are returned by the SELECT query mentioned above, provided that you have all the stored procedures defined in the table rows are available in the database. I had created the stored procedures dbo.sp_generate_merge_scdbk and dbo.sp_generate_merge with the same parameters definition. That's the reason the package executed successfully.
You have the right concept, just need to use some concepts like variables, a foreach loop and parameters on the Execute SQL Task.
Control Flow
Your Control Flow would look something like this
Variables
I have 6 variables defined in SSIS
Dimension | String | VARIETY
ETLSchema | String | stg
ETLTable | String | vw_VARIETY
Execute | Int32 | 1
RecordSet | Object | System.Object
Schema | String | dim
The first Execute SQL Task will be a query or something enumerable like it. Currently, have a hard coded query to produce the supplied query values. Your solution could just be a chain of SELECT's UNIONed together. The goal of this step is to populate the RecordSet variable.
My Execute SQL Task returns a full result set
and I push that into my object thusly
ForEach Loop Container (ADO Recordset)
The ForEach Loop Container is going to consume that enumerable thing we established beforehand. It will go through each row and we will pop the values out of the object and assign them into local variables.
Change the Enumerator to Foreach ADO Enumerator. Select the object we populated with results User::RecordSet and then use an enumeration mode of Rows in first table
In the Variable Mappings tab, we will identify the ordinal based location for the values (column 0 maps to variable X). The only trick here is to ensure your SSIS Variable data types match the data type in the result set from your source query. Do note it's a zero based ordinal system.
At this point, if you click run you see it enumerate through all the rows you have sent into the RecordSet variable. I find it helpful to run it at this point to make sure I have all of my data types aligned.
Inner Execute SQL Task
I have taken your query and replaced the hard coded values with place holder. An OLEDB connection will use ? while an ADO.NET will use named #varname.
In the Parameter Mapping tab, simply map those local variables to the place holders.
Now you have a nice template for running the same proc with varying values.