The problem:
I am using a linked server to call stored procedures from a remote server. While this works fine most of the times, I have a number of stored procedures that use table-valued parameters (TVPs). MSSQL cannot call remote SPs that use as parameters TVPs.
The workaround is to execute sql on the remote sql and build there the tvps. Again this works fine.
The problem is that I have to compose the string to call the SP. In the case when I have few TVPs, this is more or less easy, but I have SPs with a lot of TVPs.
Now, when profiling a Stored Procedure call, the call from .NET to sql in case of a TVP parameter stored procedure looks like:
declare #p1 <type>
insert into #p1 values(...)
insert into #p1 values(...)
...
exec myProc #p1
What I want to do is a wrapper on my server (identical with the sp remote) and within call the remote server with exec sql.
Does anyone now how can I (if I can) access this query from a stored procedure? Access it's own profiler like query so that I can just send it remote ?
Ok, so basically the solution is this (that kind of automates half of the problem) :
declare #tvpVal_string nvarchar(max) = 'declare #tvpVal myTVPType;'
set tvpVal_string += isnull(stuff((select ';insert into #tvpVal values('+...your values...+')' as [text()] from #tvpVal from xml path('')),1,1,'')+';','');
declare #sql nvarchar(max) = tvpVal_string +
'exec myProc #tvpVal=#tvpVal,
#OtherVal=#OtherVal'
exec [REMOTESRV].DB..sp_executesql #sql,'#OtherVal type',#OtherVal
Related
I'm trying to create a temp table from stored procedures, from this link
In the string he defines the sql server version. Our clients have different types of sql servers, from 2005 until 2012.
String: 'SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;','EXEC getBusinessLineHistory'
How can I use that command independently from sql server plataform
The OPENROWSET creates a dynamic link to a remote server.
http://technet.microsoft.com/en-us/library/ms190312.aspx
You can create a dynamic TSQL call to a dynamic link with changing parameters. Below is sample code. This can be converted into a store procedure with a #my_Server passed as a parameter.
Please note, this does not support multiple calls at the same time since only one table exists.
You can not use a local temp table since there might be a scoping issue with EXEC calling sp_executesql inside a stored procedure.
These are things you will need to research.
-- Set the server info
DECLARE #my_Server SYSNAME;
SET #my_Server = 'Server=(local)\SQL2008';
-- Clear the staging table
truncate table STAGE.dbo.MYTABLE;
-- Allow for dynamic server location
DECLARE #my_TSQL NVARCHAR(2048);
SET #my_TSQL =
'INSERT INTO STAGE.dbo.MYTABLE SELECT * FROM OPENROWSET(''SQLNCLI'',' + #my_TSQL +
';Trusted_Connection=yes;'', ''EXEC usp_My_Stored_Procedure'')';
-- Run the dynamic remote TSQL
exec sp_executesql #my_TSQL;
I have an Application Database (A-DB) which imports from a set of Databases (B-set-DBs, (around 50 DBs)).
The user selects 4 DBs of "B-set-DB`s" from which he wannts to import into the A-DB for his application.
I wrote an stored procedure for the import (about 4000 Lines of SQL Code) with 4 hard coded DB`s of B-set-DBs and it works perfect.
So my question is how to make the imported Database names variable?
I can not use dynamic SQL for the whole 4000 lines, because im callin functions and other stored procedures, there are a lot of parameters and strings and definitions of temporary tables and supqueries of subqueries of sub......and a lot of other weird things.
(I know it all sounds ugly but i just have to get it to run, i did not design the whole thing.)
Maybe it is possible to define a synonyme at the first line of the import stored procedure:
ALTER PROCEDURE [dbo].[test_storedProcedure]
(#DBName_1 nvarchar(512), #table_name_1 nvarchar(512))
AS
BEGIN
DECLARE #cmd nvarchar(max);
set #cmd = N'create synonym DB_SYN' +
N' for ' +
#DBName_1 + --[A70_V70_V280]
#table_name_1 --.[dbo].[UNITCHANGEMAP]
exec sp_executesql #cmd
...
SELECT * INTO A-DB
FROM DB_SYN
...
END
And afterwards work only with the Synonyms.
Or does anyone knows a way which will do the same?
BTW I am using SQL Server 2008
So i see all the 50 Databases in the Object Explorer of SQL Server.
Is this stored procedure considered Dynamic SQL or a Parameterised query?
CREATE PROCEDURE [dbo].[my_dodgy_sp]
#varchar1 varchar(50),
#varchar2 varchar(50)
AS
BEGIN
...
EXEC [dbo].[my_really_special_sp] #varchar1 #varchar2;
END
Extra chocolate donuts with cherries on top if you can tell me whether this is Dynamic / Parameterised:
CREATE PROCEDURE [dbo].[my_super_dodgy_sp]
#varchar1 varchar(50),
#varchar2 varchar(50),
#stored_procedure_name sysname
AS
BEGIN
...
EXEC #stored_procedure_name #varchar1 #varchar2;
END
EXEC [dbo].[my_really_special_sp] #varchar1 #varchar2;
Is not a Parameterised query, it is a normal call of a stored procedure.
It's depend on the content of [my_really_special_sp] if this will result in a Parameterised query.
Please provide more information, i would like to help you much more.
"Dynamic SQL" refers to building up a SQL Query String programatically. Such as adding joins, building up a where clause, etc.
Parameterised Queries are SQL Query Strings that contain variables, the values of which are supplied separately from the SQL Query String.
Neither of your examples fit these descriptions because they are both simple T-SQL calls within stored procedures.
It may seem pedantic, but if your application calls 'EXEC [dbo].[my_really_special_sp] #varchar1 #varchar2', then that is a parameterised query.
And if your SP calls sp_executesql 'EXEC [dbo].[my_really_special_sp] #var1 #var2', #var1 = 1, #var2 = 10 then...
sp_executesql is T-SQL call
'EXEC [dbo].[my_really_special_sp] #var1 #var2' is your parameterised query
#var1 = 1, #var2 = 10 are your parameters
The important point is that your examples are pre-compiled statements in an SP. The examples I tried to explain are strings that are passed to the SQL Server to parse, compile and execute.
If that string is made up programatically piece by piece, it's dynamic sql.
If that string contains variable references that are supplied separately, it is parameterised.
I hope that helps, though I can see that it may seem subjective.
As for your programming style. Your second SP has a minor 'vulnerability', in that if a user has access to it, they have access to all other SPs with the same signature, even if that user doesn't natively normally have access. This may be intentional, and/or you may validate the #spname parameter to close the vulnerability. Other than that, there is nothing I can see that can be faulted.
I'm passing View name as parameter in a Table Valued Function, and I want to fetch some data from that view by building a dynamic SQL and executing it by sp_executesql().
when try to execute the function, I get the error:
Only functions and extended stored procedures can be executed from within a function.
DBMS: SQL Server 2005
any workarounds?
set #SQLString =
N'select #Desc = Description from '
+ #TableName
+ ' where Code = #Code;'
execute sp_executesql #SQLString,
N'#Code nvarchar(500),
#Desc nvarchar(500) OUTPUT',
#Code = #Code,
#Desc=#Desc OUTPUT;
Well, you could wrap the dynamic SQL in an extended stored procedure. That would work, but I'd (strongly) advise against doing it.
SQL Server requires user-defined functions to be deterministic (with the exception of the aforementioned extended stored procedures) -- i.e. the results of the function should be uniformly predictable from the input parameters. Since stored procedures can access data from anywhere, use random numbers, etc., SQL Server will not allow you to use them inside a function.
There are other approaches you can use, such as prepopulating a table variable with your data, modifying your schema, and so forth, that will depend on your performance requirements and how you have the schema set up.
no unless you want to do a loopback query by calling an extended proc like xp_cmdshell
something like this, modify to fit your needs
CREATE FUNCTION fnBla(#id int)
RETURNS int
AS
BEGIN
DECLARE #SQL varchar(500)
SELECT #SQL='osql -S' +##servername +' -E -q "exec tempdb..prLog ''fnBla''"'
EXEC master..xp_cmdshell #SQL
RETURN #id
END
Just so that you know I would not do this this way since you are creating a loopback query and not executing the safest code
any reason you can't use a proc instead of a function?
I have a sql server stored procedure that I use to backup data from our database before doing an upgrade, and I'd really like it to be able to run the stored procedure on multiple databases by passing in the database name as a parameter. Is there an easy way to do this? The best I can figure is to dynamically build the sql in the stored procedure, but that feels like its the wrong way to do it.
build a procedure to back up the current database, whatever it is. Install this procedure on all databases that you want to backup.
Write another procedure that will launch the backups. This will depend on things that you have not mentioned, like if you have a table containing the names of each database to backup or something like that. Basically all you need to do is loop over the database names and build a string like:
SET #ProcessQueryString=
'EXEC '+DatabaseServer+'.'+DatabaseName+'.dbo.'+'BackupProcedureName param1, param2'
and then just:
EXEC (#ProcessQueryString)
to run it remotely.
There isn't any other way to do this. Dynamic SQL is the only way; if you've got strict controls over DB names and who's running it, then you're okay just truncating everything together, but if there's any doubt use QUOTENAME to escape the parameter safely:
CREATE PROCEDURE doStuff
#dbName NVARCHAR(50)
AS
DECLARE #sql NVARCHAR(1000)
SET #sql = 'SELECT stuff FROM ' + QUOTENAME(#dbName) + '..TableName WHERE stuff = otherstuff'
EXEC sp_ExecuteSQL (#sql)
Obviously, if there's anything more being passed through then you'll want to double-check any other input, and potentially use parameterised dynamic SQL, for example:
CREATE PROCEDURE doStuff
#dbName NVARCHAR(50)
#someValue NVARCHAR(10)
AS
DECLARE #sql NVARCHAR(1000)
SET #sql = 'SELECT stuff FROM ' + QUOTENAME(#dbName) + '..TableName WHERE stuff = #pOtherStuff'
EXEC sp_ExecuteSQL (#sql, '#pOtherStuff NVARCHAR(10)', #someValue)
This then makes sure that parameters for the dynamic SQL are passed through safely and the chances for injection attacks are reduced. It also improves the chances that the execution plan associated with the query will get reused.
personally, i just use a batch file and shell to sqlcmd for things like this. otherwise, building the sql in a stored proc (like you said) would work just fine. not sure why it would be "wrong" to do that.
best regards,
don
MSSQL has an OPENQUERY(dbname,statement) function where if the the server is linked, you specify it as the first parameter and it fires the statement against that server.
you could generate this openquery statement in a dynamic proc. and either it could fire the backup proc on each server, or you could execute the statement directly.
Do you use SSIS? If so you could try creating a couple ssis packages and try scheduling them,or executing them remotely.