sql server sp_executesql error with sql string - sql

I have a string that looks like this:
set #sqlstring = N'select #mindate = min(time), #maxdate = max(time) from ' + #st_churn_active_table;
I print it and it looks like this:
select #mindate = min(time), #maxdate = max(time) from derp.derp_table
I run sp_executesql with parameter definitions like this:
execute sp_executesql #sqlstring, N'#maxdate date,#mindate date'
It errors like this:
The parameterized query '(#maxdate date,#mindate date)select #mindate = min(time), #maxda' expects the parameter '#maxdate', which was not supplied.
String becomes
'(#maxdate date,#mindate date)select #mindate = min(time), #maxda'
The sql string is cut off, does anyone know why and how to fix this?
Thanks!

See: How to specify output parameters when you use the sp_executesql stored procedure in SQL Server

First of all, sql server saw the whole string. It's only the error message that truncates it. Notice the error got the name of the missing parameter right, even though the truncated sql string only had part of the name.
Second, this isn't going to work how you want it to. You can't use output parameters that way with sp_executesql.
But finally to the problem of why it's throwing an error. I can't be sure, but I suspect the problem here is that there is a type mismatch, and so it can't use the parameter you gave it. I would hope that sql server would throw a better error message (complain about a type mismatch) in that situation, but I don't have sql server handy to test with and I can't think of any other reason for this to cause a problem.

Related

SSRS Dataset Parameter on an REDSHIFT ODBC Connection

I am currently trying to run reports off redshift via ODBC with SSRS.
I expected that the query would run as the SQL is valid however it looks like SSRS is passing the Parameter name into the SQL query back to Redshift instead of the parameter value as id expect please consider the below query.
SELECT x.Col_1, y.Col_2, x.Col_3, x.Col_4
From x_table as x
JOIN Y_table as y on x.Col_4 = y.Col_4
WHERE x.Col_4 = #Col_4
AND x.col_3 >= #From and x.col_3 < #To
AND x.col_2 >= #From and x.col_2 < #To
In SSRS when I attempt to refresh the field list I get the below error,
ERROR [42702] [Amazon][Amazon Redshift] (30) Error occurred while trying to execute a query: [SQLState 42702] ERROR: column reference "From" is ambiguous
This query is using parameters to query the database to return only a subset of the data depending on the specific customer and a categorical field I cannot move the filters out of the report.
Troubleshooting steps
When running this query on redshift and removing the parameters it works fine.
When running this query on SQL Server with the parameters it works fine.
When running this query using the ? as the parameter name it works fine for the first parameter only.
When running this query using parameters other then column definitions it still fails with similar errors
Research this seems to be a common issue with ODBC data sources but without using multiple parameters most people seem to solve it by just using ? but that only works for single parameters.
I found two similar stack overflows but neither helped me solve this variation.
SSRS parameters basics with ODBC Connection
Passing Parameter from SSRS dataset to Snowflake
My suspicion is that ODBC datasets require some sort of escape or similar so that SSRS can replace the parameter names with values but I can't find this documented anywhere because if using ? as the parameter name works then surely it's just a matter of using some sort of escape.
Just in case anyone else has this issue i ended up solving this by using a linked server and OPENQUERY this is actually a pretty ideal solution because it enables you to write PGSQL into the report if you want technically you could even do subsequent joins on SQL Server data.
DECLARE #OPENQUERY nvarchar(4000), #PGSQL nvarchar(4000), #LinkedServer nvarchar(4000)
SET #LinkedServer = 'Redshift'
SET #OPENQUERY = 'SELECT * FROM OPENQUERY('+ #LinkedServer + ','''
SET #PGSQL = 'SELECT x.Col_1, y.Col_2, x.Col_3, x.Col_4
From x_table as x
JOIN Y_table as y on x.Col_4 = y.Col_4
WHERE x.Col_4 = '''''+ #Col_4 +'''''
AND x.col_3 >= '''''+ #From +''''' and x.col_3 < '''''+ #To +'''''
AND x.col_2 >= '''''+ #From+ ''''' and x.col_2 < '''''+ #To +''''''
EXEC (#OPENQUERY+#PGSQL)

T-SQL EXEC versus sp_exec

I tried the following:
declare #var2 nvarchar(30)
declare #qsql nvarchar(100)
set #var2 = N'iddelegat'
exec ('select max('+ #var2 + ') as IDexec from delegat');
set #qsql = 'select max(#varsp) as IDspexec from delegat';
exec sp_executesql #qsql, N'#varsp nvarchar(30)', #var2;
And the result:
IDexec IDspexec
-----------------------
500038 iddelegat
I could not understand why sp_executesql does not return the same result as EXECUTE. The right returned values are only in EXECUTE statement. It seems that sp_executesql does not evaluate the string 'iddelegat' to return the column.
You cannot parameterize column names or table names when using sp_executesql. So, when you plug in the value iddelegat in the exec(), you are getting the column. When you have it as a parameter to sp_executesql, you are getting 'iddelegat' -- a string with the name of the column.
The issue of what you can parameterize is not well explained in the SQL documentation. If you dig far enough, you will get this:
Where You Can Use Parameters
You can use parameters as placeholders for literal values — for either
text or numeric values. Most commonly, parameters are used as
placeholders in search conditions for individual rows or for groups
(that is, in the WHERE or HAVING clauses of an SQL statement).
This is in an obscure part of the documentation, but it has the correct general idea.
To help further understand this, the SQL engine can compile queries with parameters to get the execution plan. To do this, it needs to know the actual columns and tables in the query. Extra values -- parameters -- can be plugged in after the compilation step.
You can't parameterise column names.
Your attempt is basically the same as doing MAX(N'iddelegat') not MAX(iddelegat)
The only way of using these in dynamic SQL is to concatenate them into the string directly.
You should use the quotename function if doing so to mitigate against SQL injection possibilities.
See The curses and blessings of dynamic SQL

You must declare scalar variable #xml_var

I'm working with SQL Server 2012 Express and I'm testing this code on a Query window:
DECLARE #xml_var XML
SET #xml_var =
(
SELECT ID_CODE AS '#ProductionId',
CODE AS '#ItemId',
CODE_LEVEL AS '#ItemPackagingLevelId',
COMMISIONING_FLAG AS '#ItemFlag',
TIMESPAN AS '#TimeStamp',
USERNAME AS '#Username',
SOURCE AS '#Source'
FROM TRZIC.dbo.CODES_TEMP
FOR XML PATH('Item'),
ROOT('Commissioning')
)
GO
-- Call remote procedure passing it the xml
EXEC [UIC160\SQLEXPRESS].TRZIC.dbo.AddCommissioning #xml_var;
GO
But here, EXEC [UIC160\SQLEXPRESS].TRZIC.dbo.AddCommissioning #xml_var;, I get this error:
You must declare scalar variable #xml_var.
This is my first time I do this and I don't know how to solve this problem.
How can I solve it?
The problem is the first go:
DECLARE #xml_var XML
SET #xml_var =
(
SELECT ID_CODE AS '#ProductionId',
CODE AS '#ItemId',
CODE_LEVEL AS '#ItemPackagingLevelId',
COMMISIONING_FLAG AS '#ItemFlag',
TIMESPAN AS '#TimeStamp',
USERNAME AS '#Username',
SOURCE AS '#Source'
FROM TRZIC.dbo.CODES_TEMP
FOR XML PATH('Item'),
ROOT('Commissioning')
)
GO <--- THIS ONE HERE
-- Call remote procedure passing it the xml
EXEC [UIC160\SQLEXPRESS].TRZIC.dbo.AddCommissioning #xml_var;
GO
The go statement creates separate batches and variables are defined within a batch. And, this is actually well described in the documentation (here).
Remove that line and it should work. I also suggest that you put semicolons at the end of your statements. It helps make the code clearer, seeing where statements begin and end (and SQL Server may one day require them).
The variable scope ends after the GO statement. You should write GO after EXEC remote proc call.

Error in SQL stored procedure

I am getting the following error when I execute my stored procedure:
Msg 102, Level 15, State 1, Line 6Incorrect syntax near '2011'.(1 row(s) affected)
Here is the stored procedure:
ALTER PROCEDURE [dbo].[DeliveryFileNames]
AS
BEGIN
SET NOCOUNT ON;
declare #SQL nvarchar(4000)
Create Table #DelivTemp(
Style nvarchar(50),
Material nvarchar(50),
Filename nvarchar(100),
delivered_date date)
set #SQL=
N'insert into #DelivTemp
Select distinct Style,Material,filename
from OPENQUERY(GCS_PRODUCTION,
''SELECT LEFT(FILENAME,locate(''''_'''',FILENAME)-1)as Style,
substring_index(filename,''''_'''',2)as Material,filename,
delivered_date FROM view_delivery_log
where delivered_date > ''2011%'' order by Style '')'
exec (#SQL)
drop table dbo.DelivFN
Select * into dbo.DelivFN
from #DelivTemp
END
I am using OpenQuery to update a SQL table from a linked server on SQL Server 2008 R2.
I know that the underscore is a real issue, but I have tried a plethora of options including \, % and both single and double quotes.
Regardless I am getting the same result. I can run the query independently of the stored procedure and achieve the correct results. The filename field referenced several times is formatted 00000000_ABC4_A.png. I am using the underscore to identify the components of the file name that I need for my reporting purposes.
In addition to the the logical error of your date comparison using the % that the others have pointed out, your current issue is a syntactical error.
Since you've got a dynamic sql statement contained within another dynamic sql statement... you'll need to double-escape all of your single quotes... which you did in most of the query, except for the following line:
where delivered_date > ''2011%'' order by Style '')'
Properly escaped, would be:
where delivered_date > ''''2011%'''' order by Style '')'
Which raises the question... why are you building up the string to execute dynamically, instead of just calling the statement directly?
It's the syntax of ''2011%''. This is not a valid date. % being a wildcard means the compiler can't know what to compare against in the WHERE clause. You'd need to use an actual date: i.e. ''2011_01_01'' so the compiler can know what to compare against
I believe the stored proc exec runs under a different session, therefore you won't have access to the temp table anyway. So, it won't matter if you get that sql statement to run. You could always use YEAR(delivered_date) > 2011.
Another approach would be to use the fqn for the linked server to select into and bypass the temp table all together:
SELECT LEFT(FILENAME,locate('_',FILENAME)-1)as Style,
substring_index(filename,'_',2)as Material,filename,delivered_date
FROM [linked_server_name].[db_name].[dbo].view_delivery_log
into dbo.DelivFN

sp_executesql returns different results from view than running the query directly

I'm trying to debug a SSRS report which is showing some dodgy results. I'm using sql profiler I've grabbed the exact query it's running which is executed with exec sp_executesql.
The query is returning results from a view.
If I run the query as it stands including the sp_executesql, I get one set of results.
If I grab the query nested inside and run it on it's own, I get a different set of results.
I've got no idea how this is possible. The queries are identical and I was under the impression that sp_executesql simply executes the query.
Is there something I'm missing or how can I debug this further?
exec call looks something like this:
exec sp_executesql N'SELECT FirstName, LastName, DateOfBirth FROM ViewName WHERE
DateOfBirth >= #pStartDate AND DateOfBirth <= #pEndDate',N'#pStartDate datetime,
#pEndDate datetime',#pDate='2010-07-17 00:00:00:000',#pEndDate=''2010-07-17
23:59:59:000'
If I run that, I get one set of results.
Then if I run:
SELECT FirstName, LastName, DateOfBirth FROM ViewName WHERE
DateOfBirth >= '2010-07-17 00:00:00:000' AND
DateOfBirth <= '2010-07-17 23:59:59:000'
I get a slightly different set of results.
You are probably connecting with a different login.
This means results will be affectefd by a filter based on SUSER_SNAME or a different schema (dbo.View vs OtherSchema.View). It maybe inside the view.
You have NULL/empty string differences somewhere
Different databases or server
I would try pasting the query as is (doubling the single quotes that is) into the exec sp_executesql and verifying the results are the same as a manual run. If not, then it will be something to do with the date parameter, if the same, then its likely to be some kind of owner / security item.