Using a variable as table name fails - sql

Why does this fail with the following error message:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'reporting_rawdata_v2'.
the name of the table is "dbo.reporting_rawdata_v2" but either with/without "dbo" it still fails...
Use reporting2
Go
Declare #Backupdate varchar(25), #sql NVARCHAR(max)
Set #Backupdate = REPLACE(REPLACE(CAST(CONVERT(VARCHAR(20), SYSDATETIME(), 100) as varchar),' ','_'),':', '')
Select #Backupdate
SET #sql = 'Select * Into reporting_rawdata_BACKUP_' + #Backupdate + 'From reporting_rawdata_v2';
EXEC (#sql);

No space between dynamically named table and From
SET #sql = 'Select * Into reporting_rawdata_BACKUP_' + #Backupdate + ' From reporting_rawdata_v2';
EXEC (#sql);

Related

Syntax issue in SQL Server, using OPENROWSET

I am trying to Execute a stored procedure that requires to variables be passing into to it. One is a static, the other is a dynamic variable.
DECLARE #Filt DATETIME
SET #Filt = (SELECT DISTINCT MAX(Date) FROM Data.db.Staging)
SELECT * INTO #tempData FROM OPENROWSET('SQLNCLI', 'Server=ISR14 \MSSQL2012;Trusted_Connection=yes;', 'EXEC GetData.db.Staging #Mode = ''Date'' #Filt ')
but that doesn't work, got the error back
"Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '#Filt'."
I'm guessing it is because Filt is dynamic statement. So I tried this
DECLARE #FilterData DATETIME
DECLARE #sql VARCHAR(200)
SET #Filt = (SELECT DISTINCT MAX(AsOfDate) FROM Data.db.Staging)
SET #sql = 'EXEC GetData.db.Staging #Mode = ''Date'' #Filt = ' + #Filt
SELECT * INTO #tempData FROM OPENROWSET('SQLNCLI', 'Server=ISR14\MSSQL2012;Trusted_Connection=yes;',
#sql)
But I get the message back
"Msg 102, Level 15, State 1, Line 24
Incorrect syntax near '#sql'."
It seems that OPENROWSET can only accept strings. But I want to pass a variable that is dynamic.
You have to put the whole statement into a variable and run it, and convert #FilterData to a varchar to concatenate it.
You can't use variables with openquery/openrowset.
Try this and check the print output... if it works and looks ok, then EXEC(#sql2)
DECLARE #FilterData DATETIME
DECLARE #sql VARCHAR(200), #sql2 VARCHAR(500)
SET #FilterData = '2014-07-01'--(SELECT DISTINCT MAX(AsOfDate) FROM Data.db.Staging)
SET #sql = 'EXEC GetData.db.Staging #Mode = ''''Date'''', #Filt = ''''' + CONVERT(VARCHAR(20),#FilterData ,120) + ''''''
SET #sql2 = 'SELECT * INTO #tempData FROM OPENROWSET(''SQLNCLI'', ''Server=ISR14\MSSQL2012;Trusted_Connection=yes;'',
'''+#sql+''')'
print #sql2
--exec(#sql2)
You need to make the whole query dynamic, not sure if I got it nailed down, but something like:
DECLARE #Filt DATETIME
,#sql VARCHAR(MAX)
SET #Filt = (SELECT MAX(Date) FROM Data.db.Staging)
SET #sql = 'SELECT * INTO #tempData FROM OPENROWSET(''SQLNCLI'', ''Server=ISR14 \MSSQL2012;Trusted_Connection=yes;'', ''EXEC GetData.db.Staging #Mode = ''''Date''' +#Filt+ ')'
EXEC (#sql)

Variables in OPENQUERY "Deferred prepare could not be completed" error

I understand that you cannot include variables in OPENQUERY so the work around is dynamic SQL and I did the following:
DECLARE #etd AS DATETIME = '2014-06-28'
DECLARE #source AS VARCHAR(46)
DECLARE #dbName AS VARCHAR(30)
DECLARE #query AS VARCHAR(MAX)
DECLARE #openQuery AS VARCHAR(MAX)
SELECT TOP(1) #source = [Source], #dbName = DbName
FROM dbo.SomeTable
WHERE SystemCode = 'SomeSystem'
SET #query = 'SELECT *
FROM [' + #dbName + '].dbo.Table1 t1
LEFT JOIN [' + #dbName + '].dbo.Table2 t2 ON t1.bookno = t2.tranno
WHERE (YEAR(t1.etddate) = ' + CAST(YEAR(#etd) AS VARCHAR(4)) +
' AND MONTH(t1.etddate) = ' + CAST(MONTH(#etd) AS VARCHAR(2)) +
' AND DAY(t1.etddate) = ' + CAST(DAY(#etd) AS VARCHAR(2)) +')'
SET #openQuery = 'SELECT * FROM OPENQUERY([' + #source + '],''' + #query + ''')'
EXECUTE (#openQuery)
When I use SELECT #openQuery I don't see anything wrong with the query string, but once I execute it, I received the following error:
OLE DB provider "SQLNCLI11" for linked server "xxx.xxx.xxx.xxx,1433" returned message "Deferred prepare could not be completed.".
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 208, Level 16, State 1, Line 1
Invalid object name 'xxxx.dbo.t1'. (where 'xxxx' is the table name variable)
I've been searching for answers but I cannot find any, I really need your help guys.
You might temporarily change the EXECUTE to PRINT (PRINT #openQuery), see what SQL is actually being generated, then attempt to run the generated sql directly in SSMS. It might be obvious when you see the generated sql, but if not, you might get a more descriptive error message.

Database distribution dose not exist in sp_replmonitorsubscriptionpendingcmds

I'm creating a dynamic SQL log that will tell me the unpending transaction.
I'm trying to enter sp_replmonitorsubscriptionpendingcmds into a table for that reason in need to execute it as sp_executesql.
For some reason when I finish running the script it says
Msg 911, Level 16, State 4, Line 1
Database 'distribution' does not exist. Make sure that the name is entered correctly.
and im running it on distribution database.
Thank you for your help
set #counter = 1
while #counter <#NOR
BEGIN
select #v_publisher=servername,
#v_publisher_db=DbName,
#v_publication = DbName+'_1way',
#v_subscriber = ##servername,
#v_subscriber_db =DbName
from Serverses
where id = #counter
SET #sql = N'SELECT * INTO #pendingcmds
FROM OPENROWSET(''SQLOLEDB'',''SERVER=(LOCAL);TRUSTED_CONNECTION=YES''
,''SET FMTONLY OFF EXEC distribution.dbo.sp_replmonitorsubscriptionpendingcmds #publisher=['
+ #v_publisher + '],
#publisher_db='+ #v_publisher_db + ',
#publication='+ #v_publication + ',
#subscriber=['+ #v_subscriber + '],
#subscriber_db='+ #v_subscriber_db + ',
#subscription_type=' + CONVERT(CHAR(1),#pubtype) + ''')'
select #sql
EXEC sp_executesql #sql
set #counter=#counter+1
END

Error while passing a where clause as a stored procedure parameter

I have created following stored procedure in SQL Server,
create procedure sp_test
#columns nvarchar(max),
#tablename nvarchar(max),
#whereClause nvarchar(max)
as
DECLARE #sql AS NVARCHAR(MAX)
SET #sql = 'SELECT ' + #columns + ' FROM ' + #tablename + #whereClause;
EXEC sp_executesql #sql
I am trying to call it like this
exec sp_test 'title,name','person','where name = ''john'''
And I'm getting an error like this,
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '='.
You have an extra single quote, why not use double quote, like:
exec sp_test 'title,name','person'," where name = 'john'"
Add an extra space also here:
SET #sql = 'SELECT ' + #columns + ' FROM ' + #tablename+ ' ' + #whereClause;
Hint: It's because
SELECT title,name FROM personwhere name = 'john'
is not a valid SQL.
The reason should be obvious now and is left as an exercise to the reader...

Dynamic, cross database trigger creation

I am trying to dynamically create a number of triggers across two databases but I am having problems with the Create Trigger statement when switching databases
SET #SQL = 'SELECT Name FROM ' + #DB + '.sys.triggers WHERE Name = ' + ''''
+ #Table + '_DELTATrigger' + ''''
EXEC(#SQL)
IF ##RowCount > 0
BEGIN
SET #SQL = 'USE ' + #DB + '; DROP TRIGGER [dbo].[' + #Table + '_DELTATrigger]'
EXEC(#SQL)
END
SET #SQL = 'CREATE TRIGGER [dbo].[' + #Table + '_DELTATrigger]
ON [dbo].[' + #Table + ']
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
UPDATE [' + #Table + ']
SET [Delta] = 1
FROM inserted
WHERE inserted.[ID] = [' + #Table + '].[ID]
END;'
EXEC (#SQL)
If I run this statement I get the following issue
Error 8197, Level 16, State 4, Procedure tblBuild_DataPlate_DELTATrigger, Line 1
Message: The object 'dbo.tblBuild_DataPlate' does not exist or is
invalid for this operation.
Changing the dynamic create trigger to include the USE statement does not work as the Create Trigger has to be the first statement
SET #SQL = 'USE ' + #DB + '; CREATE TRIGGER [dbo].[' + #Table + '_DELTATrigger]
ON [dbo].[' + #Table + ']
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
UPDATE [' + #Table + ']
SET [Delta] = 1
FROM inserted
WHERE inserted.[ID] = [' + #Table + '].[ID]
END;'
EXEC (#SQL)
Error 111, Level 15, State 1, Procedure -,
Line 1, Message: 'CREATE TRIGGER' must be the first
statement in a query batch.
You can not fully qualify the object with the database in this case as you get the following error
Error 166, Level 15, State 1, Procedure -, Line 1,
Message: 'CREATE/ALTER TRIGGER' does not allow
specifying the database name as a prefix to the object name.
Is there a dynamic way around this?
This code below will run the sp_executesql on the selected database (#DB), so with this, you can create the trigger on the rigth place:
SET #SQL = 'EXEC ' + #DB + '..sp_executesql N''
CREATE TRIGGER [dbo].[' + #Table + '_DELTATrigger]
ON [dbo].[' + #Table + ']
AFTER INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
END;'''
EXEC (#SQL)