Passing multiple parameters to variables of sql command in linked server - sql

Here is a working example of how to pass parameters to a SQL statement on a linked server
EXEC ('SELECT ?, ?', 1, 2) AT [CDB]
But this method no works
EXEC ('
SET #A = ?;
SET #B = ?;
SELECT #A, #B', 1, 2) AT [LINKEDSERVER]
and generate error (the linked server is MySQL, the command is runnig in MS SQL as local server):
Msg 7215, Level 17, State 1, Line 7
Could not execute statement on remote server 'LINKEDSERVER'.
Sorry, I cannot attach the text of the message here, as it is in Czech (something like OLE DB error check status values).
However, I necessarily need to pass more parameters to variables without side effect Select.
So how do you do it?
But I don't want to use sp_executesql. In addition, I need to save the result of the execution on the linked server in a temporary table on the local server.
INSERT #Temptable (columns, ...)
EXEC (' more complex query with UNION ', params, ...) AT [LINKEDSERVER]
Jaroslav

Related

Creating a view in tempdb in SQL Server through a post request

Since I need to send the query statement through a http post request there are certain limitations.
1. It should be a one liner
2. it should be created in tempdb since i am going to drop it afterwards.
since SQL server takes CREATE VIEW statement only in new line I am feeding new line characters to the statement. here is the statement:
DECLARE #NewLineChar AS CHAR(2) = CHAR(13) + CHAR(10); ('USE tempdb;' +#NewLineChar + 'GO' +#NewLineChar +'CREATE VIEW temp_view AS select name from sys.databases')
This query gives me following error:
Msg 102, Level 15, State 1.
Incorrect syntax near 'USE tempdb;'. (Line 1)
what could be the problem ?
Thanks
edit: The same query works like this
USE tempdb;
GO
CREATE VIEW temp_view AS select name from sys.databases
where is the syntax error?
Since SQL server takes CREATE VIEW statement only in new line I am feeding new line characters to the statement.
I have never heard of such a requirement. What the documentation does state is: The CREATE VIEW must be the first statement in a query batch.
The statement you have in your question doesn't make sense. You can't just drop a VARCHAR in SSMS and expect SQL Server to just execute it.
What you probably want is something like the following:
USE tempdb;
DECLARE #stmt NVARCHAR(MAX)=N'CREATE VIEW temp_view AS SELECT name FROM sys.databases;';
EXECUTE sp_executesql #stmt;
Or in one line:
USE tempdb;DECLARE #stmt NVARCHAR(MAX)=N'CREATE VIEW temp_view AS SELECT name FROM sys.databases;';EXECUTE sp_executesql #stmt;
This is a bit long for a comment.
You can create a view in the current database with a name like _temp_<something>. You can even include session information if you want to emulate temporary tables.
Or, create a temporary table with no rows:
select top 0 *
into #temp
from <whatever>;
You can access the structure of this table.
If you are using a very recent version of SQL Server, use sp_describe_first_result_set (see here).

Running scripts - Check if a SQL Server 2008 database exists and replace if not (USE Database)

Running scripts - check if a SQL Server 2008 database exists and replace if not (USE Database)
I run a script on lots of servers. However some database names are not always the same hence we have to edit 'use database'
if DB_ID('sports') is not null -- check to see if exists
use sports
else
use SportsLive`-- use the correct one
Always one is not going to exist...
Msg 911, Level 16, State 1, Line 15
Database 'SportsLive' does not exist. Make sure that the name is entered correctly.
Any way around this?
use[xxx] must be at beginning of the code so
if you what to use this query
you need to put the rest of the code together
with the 'use[xxx]...' like in the example
DECLARE #i nvarchar(50)
DECLARE #a nvarchar(50)
SET #i =DB_NAME(coalesce((db_id('sports')),(db_id('SportsLive'))))
SELECT #i
SET #a= 'USE ['+#i+']
select * from [your table]'
EXEC (#a)

Can I use a variable as the value of the option AUDIT_GUID for the CREATE SERVER AUDIT statement?

I am trying to make the Audit_GUID value in the CREATE SERVER AUDIT command dynamic by using the NEWID() function in SQL. Below is my SQL script to do this:
USE [master]
GO
DECLARE #newGUID as uniqueidentifier
SET #newGUID = NEWID()
CREATE SERVER AUDIT Audit_Select_Queries -- Name of the Audit(unique for a Server)
TO FILE
( FILEPATH = N'XXXX' -- Folder to Store Audit Files at
,MAXSIZE = 0 MB -- 0 = UNLIMITED
,MAX_ROLLOVER_FILES = 2147483647 -- Max possible number of Files
,RESERVE_DISK_SPACE = OFF
)
WITH
( QUEUE_DELAY = 1000 -- Delay Audit actions by this time for completion
,ON_FAILURE = CONTINUE -- Database operation is more important than Audit
,AUDIT_GUID = #newGUID -- UUID of the Audit (unique for a server)
)
ALTER SERVER AUDIT Audit_Select_Queries WITH (STATE = OFF)
GO
But I get a syntax error near #newGUID saying "Incorrect syntax near '#newGUID'"
Please let me know what am I doing wrong.
EDIT: I am working on Microsoft SQL Server 2012
No ...
CREATE SERVER AUDIT is a statement – so AUDIT_GUID isn't a 'parameter' in the same way that a SQL Server parameter of a stored procedure is a parameter. If you're familiar with other languages, you could consider CREATE SERVER AUDIT as a 'special form' and, as such, you simply need to remember that it doesn't accept variables for that option.
I can understand why that's confusing as, for example, the BACKUP statement(s) do allow variables for certain 'parameters' ("options"), namely the name of the database; e.g. this is perfectly valid T-SQL:
DECLARE #databaseName nvarchar = "insert_name_of_database_here";
BACKUP DATABASE databaseName
...
For clarifying these types of questions, just consult Microsoft's documentation for the relevant version of SQL Server if you can't remember whether some parameters or options accept variables or not. [You can easily open the relevant documentation from SSMS by highlighting the statement, built-in procedure, etc. and hitting F1 on your keyboard.]
But if You're Willing to Dynamically Generate the T-SQL ...
Here's how you can use dynamic SQL – via EXECUTE or sp_executesql – to do what you're trying to do:
DECLARE #dynamicSql nvarchar(1000);
SELECT #dynamicSql = 'CREATE SERVER AUDIT
...
AUDIT_GUID = ''' + CAST(#newGUID AS nvarchar(255)) + ''''
+ '...' + ...,
EXEC sp_executesql #dynamicSql;

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

How to prevent an Insert query from enrolling into a Distributed Transaction?

I have a SQL Insert query inside a stored proc, for inserting rows into a linked server table.
Since the stored proc is getting called within a parent transaction, this Insert statement tries to use a DTC for inserting rows into the linked server.
I would like to avoid DTC from getting involved.
Is there any way I can do that (like a hint) for the Insert SQL statement to ignore transactional scope?
My suggestion is that you store whatever you want to insert into a staging table, and once the procedure is over run the cross server insert. To my knowledge there is no way of ignoring the transaction you are in once you are within the SProc execution.
In contrast, if you use .NET 2.0's System.Transaction namespace, you can tell specific statements not to participate in any parent scope transaction. This would require you to write some of your logic in code rather than stored procedures, but would work.
Here's a relevant link.
Good luck,
Alan.
Try using openquery to call the linked server query/sp instead of direct calling
That worked for me
so instead of
insert into ...
select * from mylinkedserver.pubs.dbo.authors
e.g.
DECLARE #TSQL varchar(8000), #VAR char(2)
SELECT #VAR = 'CA'
SELECT #TSQL = 'SELECT * FROM OPENQUERY(MyLinkedServer,''SELECT * FROM pubs.dbo.authors WHERE state = ''''' + #VAR + ''''''')'
INSERT INTO .....
EXEC (#TSQL)