Execute dynamic select query stored in a table - sql

I have stored select statements in a table column named RuleSql. In the future the table size will go large, so how can I execute all the stored select statements at the same time to get the result?
I have used:
EXEC sp_executesql
But it is not helpful for me.

It's very poor practice storing SQL code in a table. Have you looked at views, stored procedures or inline table-valued functions?
Anyway, to execute the stored SQL in a table you would do something like this....
DECLARE #Sql NVARCHAR(MAX);
SELECT TOP 1 #Sql = RuleSql
FROM TableName --<-- table where sql is stored
WHERE <Some Condition>
Exec sp_executesql #Sql
Just saw your edit. To execute all the queries at once you would use a cursor something like.....
DECLARE #Sql NVARCHAR(MAX);
DECLARE Cur CURSOR LOCAL FAST_FORWARD FOR
SELECT RuleSql
FROM TableName --<-- table where sql is stored
OPEN Cur
FETCH NEXT FROM Cur INTO #Sql
WHILE (##FETCH_STATUS = 0)
BEGIN
Exec sp_executesql #Sql
FETCH NEXT FROM Cur INTO #Sql
END
CLOSE Cur
DEALLOCATE Cur;

If you want this same information but for the whole database (all tables of a database) and create a table wit results you can use followin

Related

Execution of Stored Procedure for every row of table using string variable

I want to execute a stored procedure for every row of a table without using cursor or loop.
Lets say my table dbo.User contains name for following users:
create table dbo.test_User (
Name varchar(50) )
insert into dbo.test_User
values ('Deepanshu'),('IronMan'),('DoctorStrange')
I created a stored procedure which will only display the name of users (Although my real stored procedure has to do a lot of stuff)
create procedure dbo.usp_TestSP ( #name varchar(50) )
as
BEGIN
select #name
END
Now i want the stored procedure to run for all names like:
EXEC dbo.usp_TestSP 'Deepanshu';
EXEC dbo.usp_TestSP 'IronMan';
EXEC dbo.usp_TestSP 'DoctorStrange';
I created a string variable #Query which will store the t-sql query i want to execute
DECLARE #Query varchar(200);
select #Query=STUFF(
(select 'dbo.usp_TestSP '''+Name+''';'
from dbo.test_user
FOR XML PATH('')
),1,0,''
)
EXEC #Query
When i try to execute this #Query it gives me an error saying:
Could not find server 'dbo' in sys.servers. Verify that the correct server name was specified. If necessary, execute the stored procedure sp_addlinkedserver to add the server to sys.servers.
How can i execute the stored procedure for all the names using the string variable #Query?
You could use CURSOR to simulate FOR-EACH with stored procedure call:
DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT *FROM dbo.tesT_User;
DECLARE #name NVARCHAR(50);
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #name;
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC dbo.usp_TestSP #name = #name;
FETCH NEXT FROM db_cursor INTO #name;
END
CLOSE db_cursor;
DEALLOCATE db_cursor;
DBFiddle Demo
Warning:
If it would be simple function then CROSS/OUTER APPLY is a way to go.
SELECT *
FROM dbo.Test_User tu
OUTER APPLY (SELECT dbo.usp_TestSP(tu.name)) s(a);
DBFiddle Demo2
EDIT
i want to execute this without cursor or loop, using the same logic as displayed above
DECLARE #x NVARCHAR(MAX) =
(SELECT string_agg(FORMATMESSAGE('EXEC dbo.usp_TestSP #name=''%s'';', name)
,CHAR(13)) AS r FROM dbo.test_User);
PRINT #x;
EXEC(#x);
DBFiddle Demo3
And finally your code:
DECLARE #Query varchar(MAX);
select #Query=STUFF((SELECT 'EXEC dbo.usp_TestSP #name=' +QUOTENAME(Name,'''')
+ ';' from dbo.test_user
FOR XML PATH('')),1,0,'');
EXEC(#Query);
DBFiddle Demo4
What I did:
using semicolons (;) it's very good practice
changed datatype to VARCHAR(MAX)
added EXEC inside SQL
wrapped #Query with ()

Can I execute rows returned by select?

I'm wondering if I can make a script to execute returned rows. I have 2 rows returned by select designed by me and it looks like
alter table zamestnanci drop DF__zamestnan__datum__2E1BDC42 go sp_bindefault 'abc','zamestnanci.datum_pridania'
I'm droping default and making binded default.
Thanks for help.
If you can run all of your statements in a single batch, and they are already correctly terminated with a semicolon, you could build a single SQL string and execute the whole thing at once.
DECLARE #sql NVARCHAR(MAX) = (SELECT SomeColumn
FROM [Table]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)');
EXECUTE sp_executesql #sql;
Of if you wanted to execute the statements one by one you could use a cursor:
DECLARE sqlCursor CURSOR LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT SomeStatement
FROM [Table];
DECLARE #sql NVARCHAR(MAX);
OPEN sqlCursor;
FETCH NEXT FROM sqlCursor INTO #sql;
WHILE ##FETCH_STATUS = 0
BEGIN
EXECUTE sp_executesql #sql;
FETCH NEXT FROM sqlCursor INTO #sql;
END

SQL Query to delete data from tables defined in table

I'm trying to delete data from a number of tables in my SQL base.
In the database I have a table called company which contains the names of each table that I need to delete data from.
lets assume that I have 3 companies in my company table.
What I want to do is delete all records in some certain tables in each company.
So, in the company table I have the following 3 records:
1 2 3
There are also the following tables in the database which depicts each company's scanned documents.
dbo.1.documents
dbo.2.documents
dbo.3.documents
What I am trying to do is to create a SQL query that will run through the dbo.company table and clear the document tables based on the company names found there.
This is my code:
DECLARE #MyCursor CURSOR;
DECLARE #MyField varchar;
BEGIN
SET #MyCursor = CURSOR FOR
select top 1000 [Name] from dbo.Company
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField
WHILE ##FETCH_STATUS = 0
BEGIN
delete * from 'dbo.'+#MyField+'$documents'
FETCH NEXT FROM #MyCursor
INTO #MyField
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
I am not sure how the syntax should go but I imagine it is something like this.
Anybody care to chip in on how I can dynamically delete the data based on the records in the dbo.company.name?
Use dynamic sql.
Replace the delete-statement with code below (the declare can be done at the start):
DECLARE #sql NVARCHAR(1000)
SET #sql = N'delete from dbo.'+CONVERT(VARCHAR,#MyField)+'documents'
EXEC sp_executesql #sql
You can leverage dynamic sql a little differently and avoid all the hassle and overhead of creating a cursor for this. I am using the values in your table to generate a number of delete statements and then executing them. This is a lot less effort to code and eliminates that nasty cursor.
declare #SQL nvarchar(max) = ''
select #SQL = #SQL + 'delete dbo.[' + c.Name + '$documents];'
from dbo.Company
select #SQL --uncomment the line below when you are satisfied the dynamic sql is correct
--exec sp_executesql #sql

Is there a better way to execute dynamic SQL that doesn't use a cursor?

I have dynamic SQL stored in a SQL table that I have to execute under certain conditions. Currently, we use cursors to handle that for us, but I was always told to avoid cursors when possible as they aren't the most efficient way of doing things. So, my question is: how do I execute dynamic SQL without them (if there's a way)? The entire system is built around this dynamic SQL mess, so there is no changing it.
For this, just assume the table has Id AS IDENTITY and SQL AS VARCHAR fields, where the SQL field contains the SQL to be executed (obviously).
EDIT:
Basically, I want to loop through the table and execute the SQL in the SQL column.
So, a row in the table will basically look like this:
ID SQL
-- ----------------------
1 SELECT * FROM RECORD
2 SELECT * FROM PERSON
3 SELECT * FROM LOCATION
I haven't written any code because what I'd write is a cursor to traverse through the table and execute it. I just don't know of any other ways of looping a table and executing that string as a SQL query other than something like:
DECLARE #sql VARCHAR(MAX)
DECLARE _cursor CURSOR
FOR
SELECT [SQL]
FROM #tmp2
OPEN _cursor
FETCH NEXT FROM _cursor INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT ( #sql )
END
CLOSE _cursor
DEALLOCATE _cursor
You can use any number of concatenation tricks to make one big batch without using a cursor, I personally use the FOR XML trick a lot.
Here's an overview:
http://www.simple-talk.com/sql/t-sql-programming/concatenating-row-values-in-transact-sql/
However, the cursor (while generally a code smell) isn't going to contribute a terrible amount to the non-performance of this. And you will have an opportunity to handle errors etc a lot easier than with a single batch.
In addition, if you have DDL in some of those statements which has to be the first statement in a batch, then you would need to submit them in separate batches. EXEC or sp_executesql doesn't implement any batch splitting like SSMS has the GO batch separator.
Ignoring the fundamental flaws in this whole schema....
declare #sql nvarchar(max)
select #sql = ''
select #sql = #sql + SQL + ';' from #tmp2
exec sp_executesql #sql
At least we've got rid of your cursor now :)
EDIT: Code that is working for me...
create table #tmp2 (sql nvarchar(100))
insert #tmp2 values ('select * from sysobjects')
insert #tmp2 values ('Select * from sysColumns')
declare #sql nvarchar(max)
select #sql = ''
select #sql = #sql + SQL + ';' from #tmp2
exec sp_executesql #sql
drop table #tmp2

execute stored procedures returned from database table

I am working with sql server 2008
I have a database table that has a column containing a stored procedure name.
I want to query the database table which returns a list of the stored procedure names, and execute them.
The stored procedures are similar all having a select statment. The data returned in this select statement I want to insert in to a data base table.
Pseudo code looks like this:
INSERT INTO MyTable
EXECUTE sp_executesql SELECT StoredProcedureName FROM Table
Anyone able to assist me with correct sql for achieveing the above?
sp_executesql accepts a unicode string not a tsql statement. So you would need to execute your procedure(s) like this:
execute sp_executesql 'execute ' + #storedprocedurename
which will execute a single procedure.
You will need to write some iterative process to populate the #storedprocedurename variable from your source table.
This is pretty much same as #Coltech answer just with cursor.
DECLARE #spname VARCHAR(200)
DECLARE #sql VARCHAR(1000)
DECLARE your_cursor CURSOR FOR
SELECT spname
FROM yourTable;
OPEN your_cursor;
FETCH NEXT FROM your_cursor
INTO #spname;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'EXEC ' + #spname
execute sp_executesql #sql
FETCH NEXT FROM your_cursor
INTO #spname;
END
CLOSE your_cursor;