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)
Related
I am trying to create a stored procedure using an OPEN QUERY for a linked server. I am having a problem on the Where Clause.
I tried converting the where clause for the user id into varchar(10)
DECLARE #user_id as bigint = 32
SELECT * FROM OPENQUERY(LMSBUILDER,
'SELECT
cc.id,cc.user_id,cc.title,cc.library_id
,cc.parameters,cc.filtered,cc.embed_type
,ll.name, ll.title as lib_title, ll.major_version
,ll.minor_version,ll.patch_version,ll.runnable
,ll.restricted,ll.fullscreen,ll.embed_types
, ll.semantics
FROM
coursebuilder.wp_h5p_contents as cc
INNER JOIN coursebuilder.wp_h5p_libraries as ll
ON cc.library_id=ll.id
WHERE
cc.library_id IN (35,22, 34)
AND cc.user_id = '' + CONVERT(NVARCHAR(10), #user_id) + ''')
It should return all the results but instead I only got a null. Whenever I try to run it in mysql it returns values
This duplicate link is resolve your answer.
Microsoft Support How to pass a variable to a linked server query is also resolve your issue.
SQL Server 2014 (v13.0.4001.0) - this sample script hangs:
DECLARE #from int = 0
DECLARE #to int = 1000
select
*
from
TaskNote dtn
join
Participants tp on dtn.Task_ID = tp.TaskId
where
dtn.TaskNote_ID between #from and #to
But if I change variables to constants - it is all OK.
Like this:
where
dtn.DocTaskNote_ID between 0 and 1000
Also, if I remove the join, all is ok.
Can't figure out where the problem is
A possible cause for the problem you mention, in case your query lies within a stored procedure, is parameter sniffing. SQL Server compiles the query for the first time using the initial values of the parameters. In subsequent calls to the procedure the engine uses the cached execution plan which is probably not optimal for the current variable values.
One workaround this problem is to use OPTION (RECOMPILE):
select *
from TaskNote dtn
join Participants tp on dtn.Task_ID = tp.TaskId
where dtn.TaskNote_ID between #from and #to
option (recompile)
This way the query is being compiled every time the procedure is executed using the current parameters values.
Further reading:
Parameter Sniffing Problem and Possible Workarounds
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
I have a MS SQL Query that is pulling data via from a remote server. The data that I'm pulling down needs to be filtered by a date that is determined at run time.. When I run the query like this:
SELECT * FROM SERVER.Database.dbo.RemoteView
WHERE EntryDate > '1/1/2009'
then the filter is applied remotely... However, I don't actually want to use '1/1/2009' as the date - I want the date to be supplied by a user-defined function, like this:
SELECT * FROM SERVER.Database.dbo.RemoteView
WHERE EntryDate > dbo.MyCustomCLRDateFunction()
where the function is a custom CLR scalar-valued function that returns a date time... (You may ask why I need to do this... the details are a bit complicated, so just trust me - I have to do it this way.)
When I run this query, the remote query is NOT filtered remotely - the filtering is done after all of the data is pulled down (400,000 rows vs 100,000 rows) and it makes a significant difference.
Is there a way that I can force the query to do the filtering remotely?
Thanks!
You could also construct a string and use an openquery ...
set #sqlString =
' select into myTable from openquery
(remoteServer,
"SELECT * FROM Database.dbo.RemoteView WHERE EntryDate > %DTSTART"
)
'
set #sqlString =
replace(#sqlString, '%DTSTART',
(select cast(dbo.MyCustomCLRDateFunction() as char(8))
)
EXECUTE sp_executesql #stmt=#sqlString
Can't you just send a query like this, or does the clr function have to actually be called inside the select statement?
Declare #datetime datetime
Set #datetime = dbo.MyCustomCLRDateFunction()
SELECT * FROM SERVER.Database.dbo.RemoteView
WHERE EntryDate > #datetime
You need to properly decorate your CLR function to mark it as Deterministic, Precise and Data Access/System Data Access as DataAccessKind.None.
Update: Problem solved, and staying solved. If you want to see the site in action, visit Tweet08
I've got several queries that act differently in SSMS versus when run inside my .Net application. The SSMS executes fine in under a second. The .Net call times out after 120 seconds (connection default timeout).
I did a SQL Trace (and collected everything) I've seen that the connection options are the same (and match the SQL Server's defaults). The SHOWPLAN All, however, show a huge difference in the row estimates and thus the working version does an aggressive Table Spool, where-as the failing call does not.
In the SSMS, the datatypes of the temp variables are based on the generated SQL Parameters in the .Net, so they are the same.
The failure executes under Cassini in a VS2008 debug session. The success is under SSMS 2008 . Both are running against the same destination server form the same network on the same machine.
Query in SSMS:
DECLARE #ContentTableID0 TINYINT
DECLARE #EntryTag1 INT
DECLARE #ContentTableID2 TINYINT
DECLARE #FieldCheckId3 INT
DECLARE #FieldCheckValue3 VARCHAR(128)
DECLARE #FieldCheckId5 INT
DECLARE #FieldCheckValue5 VARCHAR(128)
DECLARE #FieldCheckId7 INT
DECLARE #FieldCheckValue7 VARCHAR(128)
SET #ContentTableID0= 3
SET #EntryTag1= 8
SET #ContentTableID2= 2
SET #FieldCheckId3= 14
SET #FieldCheckValue3= 'igor'
SET #FieldCheckId5= 33
SET #FieldCheckValue5= 'a'
SET #FieldCheckId7= 34
SET #FieldCheckValue7= 'a'
SELECT COUNT_BIG(*)
FROM dbo.ContentEntry AS mainCE
WHERE GetUTCDate() BETWEEN mainCE.CreatedOn AND mainCE.ExpiredOn
AND (mainCE.ContentTableID=#ContentTableID0)
AND ( EXISTS (SELECT *
FROM dbo.ContentEntryLabel
WHERE ContentEntryID = mainCE.ID
AND GetUTCDate() BETWEEN CreatedOn AND ExpiredOn
AND LabelFacetID = #EntryTag1))
AND (mainCE.OwnerGUID IN (SELECT TOP 1 Name
FROM dbo.ContentEntry AS innerCE1
WHERE GetUTCDate() BETWEEN innerCE1.CreatedOn AND innerCE1.ExpiredOn
AND (innerCE1.ContentTableID=#ContentTableID2
AND EXISTS (SELECT *
FROM dbo.ContentEntryField
WHERE ContentEntryID = innerCE1.ID
AND (ContentTableFieldID = #FieldCheckId3
AND DictionaryValueID IN (SELECT dv.ID
FROM dbo.DictionaryValue AS dv
WHERE dv.Word LIKE '%' + #FieldCheckValue3 + '%'))
)
)
)
OR EXISTS (SELECT *
FROM dbo.ContentEntryField
WHERE ContentEntryID = mainCE.ID
AND ( (ContentTableFieldID = #FieldCheckId5
AND DictionaryValueID IN (SELECT dv.ID
FROM dbo.DictionaryValue AS dv
WHERE dv.Word LIKE '%' + #FieldCheckValue5 + '%')
)
OR (ContentTableFieldID = #FieldCheckId7
AND DictionaryValueID IN (SELECT dv.ID
FROM dbo.DictionaryValue AS dv
WHERE dv.Word LIKE '%' + #FieldCheckValue7 + '%')
)
)
)
)
Trace's version of .Net call (some formatting added):
exec sp_executesql N'SELECT COUNT_BIG(*) ...'
,N'#ContentTableID0 tinyint
,#EntryTag1 int
,#ContentTableID2 tinyint
,#FieldCheckId3 int
,#FieldCheckValue3 varchar(128)
,#FieldCheckId5 int
,#FieldCheckValue5 varchar(128)
,#FieldCheckId7 int
,#FieldCheckValue7 varchar(128)'
,#ContentTableID0=3
,#EntryTag1=8
,#ContentTableID2=2
,#FieldCheckId3=14
,#FieldCheckValue3='igor'
,#FieldCheckId5=33
,#FieldCheckValue5='a'
,#FieldCheckId7=34
,#FieldCheckValue7='a'
It is not your indexes.
This is parameter-sniffing, as it usually happens to parametrized stored procedures. It is not widely known, even among those who know about parameter-sniffing, but it can also happen when you use parameters through sp_executesql.
You will note that the version that you are testing in SSMS and the version the the profiler is showing are not identical because the profiler version shows that your .Net application is executing it through sp_executesql. If you extract and execute the full sql text that is actually being run for your application, then I believe that you will see the same performance problem with the same query plan.
FYI: the query plans being different is the key indicator of parameter-sniffing.
FIX: The easiest way to fix this one assuming it is executing on SQL Server 2005 or 2008 is to add the clause "OPTION (RECOMPILE)" as the last line of you SELECT statement. Be forewarned, you may have to execute it twice before it works and it does not always work on SQL Server 2005. If that happens, then there are other steps that you can take, but they are a little bit more involved.
One thing that you could try is to check and see if "Forced Parameterization" has been turned on for your database (it should be in the SSMS Database properties, under the Options page). To tunr Forced Parameterization off execute this command:
ALTER DATABASE [yourDB] SET PARAMETERIZATION SIMPLE
I ran into this situation today and the fix that solved my problem is to use WITH (NOLOCK) while doing a select on tables:
Eg: If your stored proc has T-SQL that looks like below:
SELECT * FROM [dbo].[Employee]
Change it to
SELECT * FROM [dbo].[Employee] WITH (NOLOCK)
Hope this helps.
I've had off-hours jobs fubar my indexes before and I've gotten the same result as you describe. sp_recompile can recompile a sproc... or, if that doesn't work, the sp_recompile can be run on the table and all sprocs that act on that table will be recompiled -- works for me every time.
I ran into this problem before as well. Sounds like your indexes are out of whack. To get the same behavior in SSMS, add this before the script
SET ARITHABORT OFF
Does it timeout as well? If so, it's your indexing and statistics
It's most likely index-related. Had a similar issue with .Net app vs SSMS (specifically on a proc using a temp table w/ < 100 rows). We added a clustered index on the table and it flew from .Net thereafter.
Checked and this server, a development server, was not running SQL Server 2005 SP3. Tried to install that (with necessary reboot), but it didn't install. Oddly now both code and SSMS return in subsecond time.
Woot this is a HEISENBUG.
I've seen this behavior before and it can be a big problem with o/r mappers that use sp_executesql. If you examine the execution plans you'll likely find that the sp_executesql query is not making good use of indexes. I spent a fair amount of time trying to find a fix or explanation for this behavior but never got anywhere.
Most likely your .Net programs pass the variables as NVARCHAR, not as VARCHAR. Your indexes are on VARCHAR columns I assume (judging from your script), and a condition like ascii_column = #unicodeVariable is actually not SARG-able. The plan has to generate a scan in this case, where in SSMS would generate a seek because the variable is the right type.
Make sure you pass all your string as VARCHAR parameters, or modify your query to explicitly cast the variables, like this:
SELECT dv.ID
FROM dbo.DictionaryValue AS dv
WHERE dv.Word LIKE '%' + CAST(#FieldCheckValue5 AS VARCHAR(128)) + '%'