I am using SSRS reports and now I want to change data-source base on parameter. I had all ready tried to create a dynamic data source base on parameter and it works perfect on our local environment. But on production we are not able connect database due to security issue.
To overcome the security issue. we had created two data source "ProdDB" and "ArchDB" in reporting server and map with my report's data source
Now I want to know how we can Switch data source base on parameter like
Report parameter #dbsource = "Prod"
if #dbsource.value = "Prod" then
datasource = "ProdDB
Else
DataSource = "ArchDB"
Here is what you can do
Create two report parameters as databaseName and DatabaseServer
in datasource-> properties -> connection String -> expression write a connection string as below
="Data Source=" + Parameters!databaseServer.Value + ";Initial Catalog=" + Parameters!databaseName.Value
This will ask database name and database server as a report parameters, if you are running the report as data driven subscriptions you can pass these parameters dynamically from a query or static subscription parameters.
Related
There are 4 Connection strings with different SQL Servers (which I set up in SSIS Connection Managers section):
Database name is same in all the servers:
SERVER DATABASE
dbTestServer dbFees (Main Server and Database)
dbTestServer1 dbFees1
dbTestServer2 dbFees1
dbTestServer3 dbFees1
dbTestServer is the OLEDB Source and other Servers are OLEDB Destination that needs to be updated everytime we run package.
Now, I want to take data from dbTestServer-dbFees and copy to all the other databases. I created a Dataflow task to copy data from dbTestServer to dbTestServer1.
But I need to put this data flow task inside ForEach Loop container to change the connection/Server dynamically so that it will work like:
First run- By default OLEDB Source is set to dbTestServer and OLEDB Destination is set to dbServer1 and data is copied from dbFees to dbFees1.
Second run- OLEDB Source is set to dbTestServer and OLEDB Destination is set to dbServer2 and data is copied from dbFees to dbFees1
Third run- OLEDB Source is set to dbTestServer and OLEDB Destination is set to dbServer3 and data is copied from dbFees to dbFees1.
I need step by step solution as I am new to SSIS packages and I tried multiple solutions but NOTHING worked so far!
Appreciate your help!
Thank you
I suggest using FOR LOOP.
My logic is to increment variable on each loop and create an expression with a connection string and a number of iteration.
1st step is to create Connection Manager with server name dbTestServer1 and database name dbFees1
2nd step will be to add a connection manager to OLE DB Destination
3rd step is to create 2 variables: ConnString and Iteration.
For Iteration default value set to 1, because you need dbTestServer 1
ConnString you need to set like your initial connection string, just on place 1 in dbTestServer1 to set (DT_STR, 1, 65001)#[User::Iteration].
Like on next 2 pictures:
When you set variables, you need to set expression in OLE DB Connection Manager.
From drop-down select connection string and type #[User::ConnString].
And finally set FOR LOOP like on picture
NOTE: I can't test package because I don't have server names like you, but this is logic of how to solve your problem. And this is only solution for what you asked, you must create whole package on your own.
For main server and database, just add one OLE DB Source with static names for server name and database name.
And you don't need script task if you using my logic.
Here is the code I have used to dynamically change connection server/database inside C# Script task in SSIS:
Variables I pass to the C# Script task under ReadOnlyVariables:
(set these up in your Variables inside SSIS)
User::DatabaseListOnThisLoop_ConnectionString
User::DatabaseListOnThisLoop_DatabaseName
This is the name of the connection string I am dynamically change that is in my ConnectionMangers in SSIS:
SourceServerDBForClassification_Dynamic
FULL SCRIPT from my C# Script task inside SSIS. As long as you setup the variables and put the 2 in above in the ReadOnly section of the script task, you should be able to just copy/paste the entire code below into your C# Script task.
NOTE: The Namespace may give you an issue so may want to keep the one that is generated in your code when adding the script task.
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Windows.Forms; // dont think this is needed, I used this for message box for some testing, but leaving here just in case
namespace ST_f8d6dad17af541bbb0010c9fce3ccbb0
{
[Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute]
public partial class ScriptMain : Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
{
public void Main()
{
// get connection string from variable
string ServerConnectionStringOnThisLoop = Dts.Variables["DatabaseListOnThisLoop_ConnectionString"].Value.ToString();
string DatabaseOnThisLoop = Dts.Variables["DatabaseListOnThisLoop_DatabaseName"].Value.ToString();
// this could change depend on what type of connection you are using for provider and other settings
string DynamicConnectionString = "Data Source=" + ServerConnectionStringOnThisLoop + ";Initial Catalog=" + DatabaseOnThisLoop + ";Provider=SQLNCLI11.1;Integrated Security=SSPI;";
// Add the OLE DB connection manager set to existing connection
ConnectionManager SourceServerDBForClassification_Dynamic = Dts.Connections["SourceServerDBForClassification_Dynamic"];
// now set the dynamic connection above to the connection string passed in from SSIS package
SourceServerDBForClassification_Dynamic.ConnectionString = DynamicConnectionString;
// now set the package connection to the one we just created from using the variable from the SSIS package
Dts.Connections["SourceServerDBForClassification_Dynamic"].ConnectionString = SourceServerDBForClassification_Dynamic.ConnectionString;
Dts.TaskResult = (int)ScriptResults.Success;
}
enum ScriptResults
{
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success,
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
};
}
}
how to create ssrs report that shows database names as a dropdown filter and user can select the database name and connect dynamically and run the report.
The Server name is same, just the databases must by dynamic.
Please let me know.
You need to create a datasource in your report, this will not work on a shared datasource.
Create a new datasource and then next to the connection string field, click the fx button. You can build your connection string using parameter values to change the database. The expression might look something like this..
="Data Source=MyServerName;Initial Catalog=" & Parameters!myDatabaseParameter.Value & ";Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
I need to set the connection string somewhere in one place in SSRS project in order to use it in Data Sources across all the reports. As SSRS doesn't support project params it's recommended to create Shared DataSet instead, e. g. HostParam.rds
SELECT 'localhost' AS GlobalParameter
The question is how to access it further in expression in Data Source connection string
="Data Source=" + HostParam.GlobalParameter + ";Initial Catalog=xxx"
gives an error 'HostParam' is not declared
You can setup a shared datasource at the project level, this contains just the connection to the database.
You then select this shared datasource when creating datasets (this works for both shared datasets or embedded datasets).
If you change the connection in the shared data source, this is reflected in all the datasets and therefore reports that reference it.
In my work place's SQL Server 2008 set up, we have set up a database table called DATE_RANGE_CONTROL with two columns: startDate and endDate of data type DateTime. Our SSIS packages extract data from an Oracle Database for a set date range so most of our SQL code in the DB Source Editor takes the form of:
SELECT COLUMN1,COLUMN2,COLUMN3,TRANSACTION_DATE
FROM SOURCE_DATABASE_TABLE
WHERE TRANSACTION_DATE BETWEEN startDate AND endDate
What I want to do is to set the startDate and endDate dynamically so that at the time of execution, the query gets the values from the DATE_RANGE_CONTROL table. I have looked at using the SQL Command from variable as an option but I cannot figure out how to feed the values of startDate and endDate from the DATE_RANGE_CONTROL table to the DB Source SQL command.
I have done something similar in the SQL SERVER 2000 DTS packages where I was setting the SQLCommand property of the data pump dynamically using the ACTIVEX script task. How do i do it in SSIS?
After spending a considerable amount of time on Google and looking through the Microsoft SQL Server 2008 SSIS documentation, I have finally cracked it. So proud of myself. The solution is thus:
In SQL Server Business Intelligence Development Studio, create a new SSIS package.
Create 3 variables, I called mine startDate, endDate and strDataSourceSQL. Make sure they all have a scope level of Package and ensure thay have Data Types of Int32, Int32 and String respectively..
On the Control Flow tab, drag a Script Task from the toolbox to the Control Flow pane. Right click it and choose edit from the pop up menu.
On the Script page, click on the ellipsis to the right of ReadWriteVariables. Tick the variables you created in step 1 i.e. user::startDate, user::endtDate and user::strDataSourceSQL. You can rename your script task on the General page. It is good practice.
On the Script page,click on the Edit Script... button to reveal a visual studio IDE pane with some pre-written code.
Make the following changes. At the top of the page, you will notice a few lines the import namespaces and classes to use. Edit the lines of code and make sure you have the following lines:
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Runtime;
using System.Data.OleDb;
Go to the menu Project > Add Reference. On the .NET tab, make sure you select Microsoft.SqlServer.DTSPipelineWrap and Microsoft.SqlServer.DTSRuntimeWrap Credit to DotNetMonster for the tip.
In the public void Main() method, you will see a comment that says // TODO: Add your code hereWe will replace that line or add the following lines of code. By the way, I am using OLEDB for my data source and data destination.
//Declare variables
Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100 cmParams;
System.Data.OleDb.OleDbConnection oleDbConn;
ConnectionManager cm;
Int32 strStartDate;
Int32 strEndDate;
String startDateSQL = "SELECT StartDate FROM DATE_RANGE_CONTROL";
String endDateSQL = "SELECT EndDate FROM DATE_RANGE_CONTROL";
//Declare and assign Connection manager
cm = Dts.Connections["YOUR_OLEDB_CONNECTION_MANAGER_NAME"];
//Set Connection paramters
cmParams = cm.InnerObject as Microsoft.SqlServer.Dts.Runtime.Wrapper.IDTSConnectionManagerDatabaseParameters100;
//Instantiate the Oledb connection
oleDbConn = cmParams.GetConnectionForSchema() as OleDbConnection;
Assign the strStartDate and strEndDate variables, the result of running a function that we will display later. All it does provide an SQL command to the OLEDB connection.
strStartDate = (int)assignSQLCommand(startDateSQL,oleDbConn).ExecuteScalar();
strEndDate = (int)assignSQLCommand(endDateSQL, oleDbConn).ExecuteScalar();
//Assign the startDate and endDate variables the value of the SQL resultset
Dts.Variables["startDate"].Value = strStartDate;
Dts.Variables["endDate"].Value = strEndDate;
Declare a variable called dataSourceSQL of type string and assign your DataSource SQL code to it. Replace the date range values with the values of the variables above. For me, the code is as follows:
String dataSourceSQL = "SELECT COLUMN1,COLUMN2,COLUMN3,TRANSACTION_DATE
FROM SOURCE_DATABASE_TABLE
WHERE TRANSACTION_DATE BETWEEN '"+Dts.Variables["startDate"].Value +"' AND '"+Dts.Variables["endDate"].Value+"'";
Then assign the value of dataSourceSQL to your strDataSourceSQL package variable
Dts.Variables["strDataSourceSQL"].Value = dataSourceSQL ;
Outside the curly brackets of the public void Main() method, add the following function we discussed earlier.
public OleDbCommand assignSQLCommand(String SqlCommand, OleDbConnection oledbconn)
{
return new System.Data.OleDb.OleDbCommand(SqlCommand, oledbconn);
}
Go to the menu Build > Build [script name]. Save it and close the script page. Finally, all that is left is to create a Data Source task. Go to the Data Flow tab, drag an OLE DB DB Source to the pane. Right click on the OLE DB Source and choose edit. On the Connections Manager page, select your OLE DB connection manager and on the Data access mode choose SQL command from variable. In the variable name select user::strDataSourceSQL. As long as you set up your script task to run before your data flow, the job is done!
This is how I could do that.
In the OLE DB Source, enter your sql statement and enter ? as the parameter.
click [Parameters...] button and pick your variable from the list
I want to use the same Reports(.rdl) to generate the reports for 24 databases.
For instance if there is a user table in my reports(.rdl), then the datasource for the report(.rdl) should change dynamically. Now, I'm making 24 different Reports for 24 databases.
I want a single report(.rdl) with the datasource changed at the runtime.
The way to achieve this could be adding 3 parameters to your report (.rdl) file
ServerName
DatabaseName
and if required
Password
Then change the connection string for the datasource like
="data source=" & Parameters!ServerName.Value & ";initial catalog=" & Parameters!DatabaseName.Value
Only small issue with this approach is the paramnames are visible in the URI so caveat emptor
I found an alternative solution to my problem. I created a single (.rdl) Report file which used the user which had a right in all the databases gave the datasource as this user, and the database as in which I made single procedure in a database, suppose admin database(used for all procedure which are common to all), In that procedure I executed the procedure which is present in other databases like this:
set #sSql='Execute '+ #databasename + '.'+ #username + '.'+'GetData'
EXEC (#sSql)
where username and Databasename are present in the table(for all database) and a column name sentDate which is update to todays date after executing the procedure for that databaseName, so that the datasource moves to next after username and databasename after executing the procedure. And made the subscription to run after 10 min, so that it can send the reports of all databases, by getting data form different database in each execution.