execute stored procedures returned from database table - sql

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;

Related

How to create a simple stored procedure with table name as an input

I am using SQL Server 2017 and I would like to create a stored procedure with a single table name as an input variable. All I want the procedure to do is update that table in a variety of ways. This project will be done twice a year, and the columns will always be the same, so I would like to try this as a stored procedure, so I do not have to highlight several lines of code and executing each time.
Is there a simple way to pass a table name through a stored procedure which updates the table (adding columns, calculating columns, replacing nulls in columns etc). In a basic example, one task would be just replaces nulls with 0s in a column. I am not sure how to set this up though. DO I have to declare every column in the table too?
CREATE PROCEDURE updteleform
#tablename TABLE
AS
BEGIN
UPDATE #tablename
SET Recog = 0
WHERE Recog IS NULL
END
GO
I'm assuming you want to update a physical table. SQL Server table variables don't work that way, rather they are a way to pass a transient result set to a stored procedure. There is no persistence if your stored procedure does not do so.
If you are looking to update the same table, then just write the procedure to work on that table.
If you are looking to update multiple tables using the same script then you should change your procedure to accept a string parameter that would be the name of the table you want it to work on and then use dynamic SQL in your stored procedure.
Something like
CREATE PROCEDURE updteleform #tablename sysname
AS
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'
update ' + QUOTENAME(#tablename) + '
set Recog= 0
where Recog is null;';
EXEC sp_executesql #sql;
END
GO
And then call it with something like:
EXEC updteleform #tablename = 'table1';
EXEC updteleform #tablename = 'table2';
EXEC updteleform #tablename = 'table3';
...

Execute dynamic select query stored in a table

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

iterative executing stored procedure with a set based approach

I have an issue where I am trying to replace the following code with a different solution. Currently I am using a cursor but it is running to slowly. I am under the understanding that iterative solutions can only be completed with cursors or while loops but I am trying to find a set based approach and running out of ideas. I was hoping that I could find some inspiration here. Thanks all.
--used to find a unique list of Some_ID
#Id1, #Id2, #Id3
DECLARE SomeCursor CURSOR FOR
SELECT SOME_ID FROM SomeTable
WHERE ID1=#Id1 AND ID2=#Id2 and ID3=#Id3
OPEN SomeCursor
FETCH NEXT FROM SomeCursor INTO #SomeID
WHILE ##Fetch_Status = 0
BEGIN
Print #SomeID
--simply populates a single table with values pulled from
--other tables in the database based on the give parameters.
EXEC SP_PART1 #SomeID, #parameters...
print 'part 2 starting'
EXEC SP_PART2 #SomeID, #parameters...
FETCH NEXT FROM SomeCursor INTO #SomeID
print getdate()
END
CLOSE SomeCursor;
DEALLOCATE SomeCursor;
Your only option to make this set-based is to rewrite the sps to make them set-based (using table-valed parameters intead of individual ones) or to write set based code in this proc instead of re-using procs designed for single record use. This is a case where code re-use is usually not appropriate.
I'm not too sure what you want, but why not use your select statement to create your sql scripts and execute them all at once with something like this.
DECLARE #sql VARCHAR(MAX);
SELECT #sql = COALESCE(#sql,'') + 'EXEC SP_Part1 ' + SOME_ID + '; EXEC SP_Part2 ' + SomeID + '; GO '
FROM SomeTable
WHERE ID1=#Id1 AND ID2=#Id2 and ID3=#Id3
EXEC (#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

MSSQL: How do you script Stored Procedure creation with code?

I am trying to query for a list of stored procedure definitions using information_schema.routines that exist in one database but not in another.
SELECT
t1.Routine_Definition
FROM
[server1].MyDatabase.INFORMATION_SCHEMA.Routines t1
LEFT JOIN
[server2].MyDatabase.INFORMATION_SCHEMA.Routines t2 ON t1.Routine_Name = t2.Routine_Name
WHERE
t2.Routine_Name is null
This gives me the query definitions in a single line so when I have a comment like this
--Some comment
SELECT Column
FROM Somewhere
The SQL gets commented out and I cannot use the definition to create the SP.
How to I parse this back with the proper line breaks?
or
Is there a better way to get these scripts (using code)?
The stored procedure is only displayed on one line in Management Studio. If you run the query with results to text, or use the following, you will get the correct line breaks:
declare #sql varchar(8000) -- varchar(max) in SQL 2005+
SELECT
#sql = t1.Routine_Definition
FROM
INFORMATION_SCHEMA.Routines t1
print #sql
DECLARE MY_CURSOR Cursor
FOR
SELECT
t1.Routine_Definition
FROM
[server1].MyDatabase.INFORMATION_SCHEMA.Routines t1
LEFT JOIN
[server2].MyDatabase.INFORMATION_SCHEMA.Routines t2 ON t1.Routine_Name = t2.Routine_Name
WHERE
t2.Routine_Name is null AND
LEN(t1.Routine_Definition) < 4000
Open My_Cursor
DECLARE #sql VARCHAR(MAX)
FETCH NEXT FROM MY_Cursor INTO #sql
While (##FETCH_STATUS <> -1)
BEGIN
IF (##FETCH_STATUS <> -2)
Print #sql
FETCH NEXT FROM MY_CURSOR INTO #sql
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
GO
Here is how I implemented ck's solution...
the INFORMATION_SCHEMA view only returns the first 4000 characters in the definition. (Ideally you wont have SP that are that long)You will want to script those manually or some other way.
I think the easiest way of getting your stored procedures is to use the Import/Export utility that is built into SQL Server Management Studio. From there you can export your Stored Procedure Objects into the code window or to a file that you can immediately run.