I want to send the date range and employee ids from SSRS to Oracle package. Does anyone knows how to do it? Even if i try to declare an oracle package with three in parameters from_date, to_date and employee_id it works fine with one employee id. But fails if i select multiple employees in SSRS web interface saying wrong number of parameters. Does anyone know how to handle this?
Normally with SQL and SSRS you would do something like
Select * From Table where Table.Field in #Param
Oracle is different of course and depends on the Connection Type you are using.
ODBC connection you would use something like:
Select * From Table where Table.Field = ?
Order of the parameters is important here so be careful.
OLEDB connection you would use something like:
Select * From Table where Table.Field = :Param
However, none of the above work with multi selecting of the Parameters. You could do this:
=”Select * From Table where Table.Field in (‘” + Join(Parameters!parameter.Value,”‘, ‘”) + “‘)”
or
=”Select * From Table where Table.Field in(” + Join(Parameters!parameter.Value,”, “) + “)” if the values or your field is only numeric.
Here are a couple of good articles that you can look at. It has a better explanation than I can give personally without more information; Details of your Oracle Environment, Connection Type, etc.
Quick Reference:
Be sure your Oracle version is 9 or greater, none of this works on
versions 8 or older.
When using parameters with Oracle, use a : instead of an # sign –
:param instead of #param.
Add an ‘ALL’ option to your datasets that supply values for
multivalued drop down parameters.
Check for the ALL in your where clause by using “where ( field1 in (
:prmField1 ) or ‘ALL’ in ( :prmField1 ) )” syntax.
You can execute your query from the dataset window, but can only
supply 1 value. However that value can be ‘ALL’.
Educate your users on ‘ALL’ versus ‘(select all)’ .
Another good article about Multiple Parameters in SSRS with Oracle: Davos Collective Which is referenced in the top portion.
Hope this helps!
Related
I want to set local variables or pass parameters from Excel to SQL. I've found similar questions, but all referred to old versions of Excel and/or the answers showed how to filter or manipulate output from a generic SQL query in the Power Query Editor, rather than pass a parameter or modify the SQL, so that the SQL Server supplies data in the needed form.
I'm building a large Microsoft Excel spreadsheet that depends on ten different SQL queries, all against a common SQL Server database. Excel and SQL Server are installed on my laptop and are current versions (as of 16 Mar 2022). All ten queries share a common date restriction, imposed in the WHERE clauses of the queries. The tables accessed and the form of output are very different, so there is no easy way to combine the ten queries into a single query. The queries contain multiple levels of aggregation (e.g. SUM(...)) so I need to restrict the records accessed prior to aggregation and passing results from the query back to Excel.
As currently written, each query begins by setting two date values in local variables. For example,
DECLARE #BEGIN_DATE AS smalldatetime;
DECLARE #END_DATE AS smalldatetime;
#BEGIN_DATE = CAST('2021-03-01 00:00' AS smalldatetime);
#END_DATE = CAST('2021-03-02 23:59' AS smalldatetime);
Every one of the ten queries includes a line in the WHERE clause similar to
WHERE
PickUpDate BETWEEN #BEGIN_DATE AND #END_DATE
Every query will use the same pair of dates. However, the column filtered (PickUpDate above) changes from one query to the next.
As it is, I have to manually edit each of the ten queries to change the two dates--twenty edits in all. This is time-consuming and error-prone. Ideally, I'd like to set the date range in the spreadsheet, in a pop-up dialog box, or any other convenient way and pass the dates to the SQL queries. Then by selecting Data > Refresh All in Excel, update all my tables at once.
Is this possible, and if so, how does one do it?
The answer from David Browne is generally on-target. But I found some difficulties reading data from an Excel table directly into the SQL, given security restrictions in the latest version of Excel/Power Query. Also, since this was the first time I worked directly in M-code and the advanced editor, it was challenging to fill-in the gaps.
I finally got a nice solution running; here is what worked for me.
First, I stored the parameter values in a two-column table. My table is named "ParameterTable" with column headers named "Parameter_Name" and "Value". The value(s) to pass to SQL Server are stored in the Value column. My table has two rows with row entries labeled "Begin_DateTime" and "End_DateTime".
Secondly I created a callable function named “ftnGetParameter.” Select Data > Get Data > From Other Sources > Blank Query. Then select “Advanced Editor.” Delete any boilerplate added by Excel, and enter and save this function
let theParameter=(TableName,ParameterLabel) =>
let
Source=Excel.CurrentWorkbook(){[Name=TableName]}[Content],
value = Source{[Parameter_Name=ParameterLabel]}[Value]
in
value
in
theParameter
Thirdly, code-up your SQL statement as usual. I was trying to pass dates to SQL, so I initially coded with string literals. Enter the query in the usual way. I used Data > Get Data > From Database > From SQL Server Database. Then pasted in the SQL. The two relevant lines in my query looked like this:
DECLARE #BEGIN_DATE AS SMALLDATETIME='2021-01-01 00:00';
DECLARE #END_DATE AS SMALLDATETIME='2021-12-31 23:59';
You could skip this step, but it allowed me to get complex SQL code entered, formatted, and running before I invoked the function to pass the parameters.
Finally, simply replace the string literals in the SQL with code to call the function. My first few lines of M-code looks like this:
let
Source = Sql.Database("DESKTOP-04P8E8C", "nfbdata",
[Query=
"
DECLARE #BEGIN_DATE AS SMALLDATETIME= '" & ftnGetParameter("ParameterTable","Begin_DateTime") & "';
DECLARE #END_DATE AS SMALLDATETIME='" & ftnGetParameter("ParameterTable","End_DateTime") & "' (… the query continues )
Excel will issue some warnings about running the query and prompt you to edit permissions. Once permission has been granted, the function reads the text from the parameter table and passes it into the SQL.
I found that the function call was not optional. Apparently, importing the code directly into a native call to SQL Server is considered an unacceptable security risk.
Many thanks to Mr. David Browne. His post definitely points in the right direction.
You can reference a table on a sheet from Power Query and integrate values from that table into your other queries. Eg if ParameterTable is a single-row table on some worksheet with a column called "StartDate", something like
let
theDate = Date.From( Record.Field(Table.First(ParameterTable),"StartDate") ),
Source = Sql.Databases("localhost"),
AdventureWorksDW2017 = Source{[Name="AdventureWorksDW2017"]}[Data],
dbo_DimDate = AdventureWorksDW2017{[Schema="dbo",Item="DimDate"]}[Data],
#"Filtered Rows" = Table.SelectRows(dbo_DimDate, each [FullDateAlternateKey] = theDate )
in
#"Filtered Rows"
for M query folding, or
let
theDate = Date.From( Record.Field(Table.First(ParameterTable),"StartDate") ),
sql = "
select *
from dimDate
where FullDateAlternateKey = '" & Text.From(theDate) & "'
",
Source = Sql.Database("localhost", "adventureworksdw2017", [Query=sql])
in
Source
for dynamic SQL.
I am trying to extract individual dates from a varchar column in a SQL Server 2016 tablet that are stored comma separated and am not sure how to proceed. The data is setup like this:
article Consolidation_Order_Cut_Off_Final_Allocation
------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
011040 01/13/2021,03/10/2021
019099 01/13/2021,01/27/2021,02/24/2021,03/24/2021,04/28/2021,05/26/2021,06/23/2021,07/28/2021
019310 01/27/2021,02/03/2021,03/10/2021,04/14/2021,05/12/2021,06/09/2021,07/14/2021,08/11/2021
059611 01/13/2021
Ideally - I would have each date split out into a new row. I have seen a few similar questions that use very complex functions but those seem to be for SQL Server 2008. I have also found the new function STRING_SPLIT but that would seem to be table valued and thus have to come in the FROM. One thought I had was to declare a variable to hold this column and then use something like select * FROM string_split(#dates,','); however since there is more than one value in that list that returns an error. I am very new to the 2016 version of SQL Server and curious if anyone has ran into a way to solve this.
String_Split() is a table valued function, so you can call it with a CROSS APPLY
Example or dbFiddle
Select A.article
,B.Value
From YourTable A
Cross Apply string_split(Consolidation_Order_Cut_Off_Final_Allocation,',') B
I have a query in classic asp where SQL statement is this:
Select * from active_Case
I verified in the DB connection it is using and found there is no such table / view. But a table does exist by the name of Cases. Internally it appears to be selecting from this table itself.
Actually this is somebody else's code. Thus I am not sure how is it possible. Is it really possible or am I missing something?
this will give you the base table name
select name, base_object_name
from sys.synonyms
where name = 'active_Case'
other than tables and view you can even check in User defined table type under types. or there might be chance your table is having a schema other than 'dbo.'
Recently I found an anomaly with SQL Server database creation. If I create with the sql query
create database 6033SomeDatabase;
It throws an error.
But with the Management Studio UI, I can manually create a database with a name of 6033SomeDatabase.
Is this expected behaviour or is it a bug? Please throw some light on this issue.
Try like this,
IF DB_ID('6033SomeDatabase') IS NULL
CREATE DATABASE [6033SomeDatabase]
I'll try to give you detailed answer.
SQL syntax imposes some restrictions to names of database, tables, and fields. F.e.:
SELECT * FROM SELECT, FROM WHERE SELECT.Id = FROM.SelectId
SQL parser wouldn't parse this query. You should rewrite it:
SELECT * FROM [SELECT], [FROM] WHERE [SELECT].Id = [FROM].SelectId
Another example:
SELECT * FROM T1 WHERE Code = 123e10
Is 123e10 the name of column in T1, or is it a numeric constant for 123×1010? Parser doesn't know.
Therefore, there are rules for naming. If you need some strange database or table name, you can use brackets to enclose it.
I'm migrating from SQL Server to PostgreSQL. I've seen from How to declare a variable in a PostgreSQL query that there is no such thing as temporary variables in native sql queries.
Well, I pretty badly need a few... How would I go about mixing in plpgsql? Must I create a function and then delete the function in order to get access to a language? that just seems error prone to me and I'm afraid I'm missing something.
EDIT:
cmd.CommandText="insert......" +
"declare #app int; declare #gid int;"+
"set #app=SCOPE_IDENTITY();"+ //select scope_identity will give us our RID that we just inserted
"select #gid=MAX(GROUPID) from HOUSEHOLD; set #gid=#gid+1; "+
"insert into HOUSEHOLD (APPLICANT_RID,GROUPID,ISHOH) values "+
"(#app,#gid,1);"+
"select #app";
rid=cmd.ExecuteScalar();
A direct rip from the application in which it's used. Note we are in the process of converting from SQL server to Postgre. (also, I've figured out the scope_identity() bit I think)
What is your schema for the table being inserted? I'll try and answer based on this assumption of the schema:
CREATE TABLE HOUSEHOLD (
APPLICANT_RID SERIAL, -- PostgreSQL auto-increment
GROUPID INTEGER,
ISHOH INTEGER
);
If I'm understanding your intent correctly, in PostgreSQL >= 8.2, the query would then be:
INSERT INTO HOUSEHOLD (GROUPID, ISHOH)
VALUES ((SELECT COALESCE(MAX(GROUPID)+1,1) FROM HOUSEHOLD), 1)
RETURNING APPLICANT_RID;
-- Added call to the COALESCE function to cover the case where HOUSEHOLD
-- is empty and MAX(GROUPID) returns NULL
In PostgreSQL >= 8.2, any INSERT/DELETE/UPDATE query may have a RETURNING clause that acts like a simple SELECT performed on the result set of the change query.
If you're using a language binding, you can hold the variables there.
For example with SQLAlchemy (python):
my_var = 'Reynardine'
session.query(User.name).filter(User.fullname==my_var)
If you're in psql, you have variables:
\set a 5
SELECT :a;
And if your logic is in PL/pgSQL:
tax := subtotal * 0.06;
Must I create a function and then
delete the function in order to get
access to a language?
Yes, but this shortcoming is going to be removed in PostgreSQL 8.5, with the addition of DO command. 8.5 is going to be released in 2010.
You can also declare session variables using plperl - http://www.postgresql.org/docs/8.4/static/plperl-global.html
you install a language that you want to use with the CREATE LANGUAGE command for known languages. Although you can use other languages.
Language installation docs
CREATE LANGUAGE usage doc
You will have to create a function to use it. If you do not want to make a permanent function in the db then the other choice would be to use a scrip in python or something that uses a postgresql driver to connect to the db and do queries. You can then manipulate or look through the data in the script. For instance in python you would install the pygresql library and in your script import pgdb which you can use to connect to the db.
PyGreSQL Info
I think that PostgreSQL's row-type variable would be the closest thing:
A variable of a composite type is
called a row variable (or row-type
variable). Such a variable can hold a
whole row of a SELECT or FOR query
result, so long as that query's column
set matches the declared type of the
variable.
You mentioned the post (How to declare a variable in a PostgreSQL query).
I believe there is a suitable answer farther down the chain of solutions if using psql and the \set command:
my_db=> \set myvar 5
my_db=> SELECT :myvar + 1 AS my_var_plus_1;