How to execute a stored procedure inside a select query - sql

SELECT col1,
col2,
col3,
EXEC GetAIntFromStoredProc(T.col1) AS col4
FROM Tbl AS T
WHERE (col2 = #parm)
How to write this SQL query in SQL Server 2008?

Thanks #twoleggedhorse.
Here is the solution.
First we created a function
CREATE FUNCTION GetAIntFromStoredProc(#parm Nvarchar(50)) RETURNS INTEGER
AS
BEGIN
DECLARE #id INTEGER
set #id= (select TOP(1) id From tbl where col=#parm)
RETURN #id
END
then we do the select query
Select col1, col2, col3,
GetAIntFromStoredProc(T.col1) As col4
From Tbl as T
Where col2=#parm

Functions are easy to call inside a select loop, but they don't let you run inserts, updates, deletes, etc. They are only useful for query operations. You need a stored procedure to manipulate the data.
So, the real answer to this question is that you must iterate through the results of a select statement via a "cursor" and call the procedure from within that loop. Here's an example:
DECLARE #myId int;
DECLARE #myName nvarchar(60);
DECLARE myCursor CURSOR FORWARD_ONLY FOR
SELECT Id, Name FROM SomeTable;
OPEN myCursor;
FETCH NEXT FROM myCursor INTO #myId, #myName;
WHILE ##FETCH_STATUS = 0 BEGIN
EXECUTE dbo.myCustomProcedure #myId, #myName;
FETCH NEXT FROM myCursor INTO #myId, #myName;
END;
CLOSE myCursor;
DEALLOCATE myCursor;
Note that ##FETCH_STATUS is a standard variable which gets updated for you. The rest of the object names here are custom.

You can create a temp table matching your proc output and insert into it.
CREATE TABLE #Temp (
Col1 INT
)
INSERT INTO #Temp
EXEC MyProc

As long as you're not doing any INSERT or UPDATE statements in your stored procedure, you will probably want to make it a function.
Stored procedures are for executing by an outside program, or on a timed interval.
The answers here will explain it better than I can:
Function vs. Stored Procedure in SQL Server

"Not Possible".
You can use a function instead of the stored procedure.

"Not Possible". You can do this using this query.
Initialize here
declare #sql nvarchar(4000)=''
Set Value & exec command of your sp with parameters
SET #sql += ' Exec spName #param'
EXECUTE sp_executesql #sql, N'#param type', #param = #param

Don't forget, if you just want to use the SP as a one-off query real quick to check something, all you have to do is pull the innards of the SP out and paste it in a new query window and do whatever you like at that point because it is no longer a SP.

Create a dynamic view and get result from it.......
CREATE PROCEDURE dbo.usp_userwise_columns_value
(
#userid BIGINT
)
AS
BEGIN
DECLARE #maincmd NVARCHAR(max);
DECLARE #columnlist NVARCHAR(max);
DECLARE #columnname VARCHAR(150);
DECLARE #nickname VARCHAR(50);
SET #maincmd = '';
SET #columnname = '';
SET #columnlist = '';
SET #nickname = '';
DECLARE CUR_COLUMNLIST CURSOR FAST_FORWARD
FOR
SELECT columnname , nickname
FROM dbo.v_userwise_columns
WHERE userid = #userid
OPEN CUR_COLUMNLIST
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #columnlist = #columnlist + #columnname + ','
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
END
CLOSE CUR_COLUMNLIST
DEALLOCATE CUR_COLUMNLIST
IF NOT EXISTS (SELECT * FROM sys.views WHERE name = 'v_userwise_columns_value')
BEGIN
SET #maincmd = 'CREATE VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
ELSE
BEGIN
SET #maincmd = 'ALTER VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
EXECUTE sp_executesql #maincmd
END
-----------------------------------------------
SELECT * FROM dbo.v_userwise_columns_value

Related

Error "Declare Scalar" when Dynamic Exec Update inside two Cursor loops

Basically I'm looking to loop through a temp table which lists certain table names which need updated, I take each table name use it to populate another temporary table of all the ID's which are to be updated..
I can select the data in each table needing updated using this structure, but cannot seem to get the inner cursor to run as it isn't picking up the temp table..
Any help would be greatly appreciated as this has been doing my nut in for the past few hours..
Cheers,
DECLARE #table INT
DECLARE #prefix nvarchar(3)
DECLARE #TableName nvarchar(50)
DECLARE #TableIdName nvarchar(50)
DECLARE #getTable CURSOR
SET #getTable = CURSOR FOR
SELECT DISTINCT(id)
FROM #t
OPEN #getTable
FETCH NEXT
FROM #getTable INTO #table
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #TableName = name FROM #t WHERE id = #table
SET #TableIdName = #TableName + 'Id'
SELECT #prefix = prefix FROM #t WHERE name = #TableName
--PRINT #table
PRINT #TableName
--PRINT #TableIdName
--PRINT #prefix
DECLARE #temptable table(rid int, rTableName nvarchar(50), rprefix nvarchar(3), rpk nvarchar(50))
EXEC ('INSERT INTO ' + #temptable + ' SELECT ' + #TableIdName + ', ' + #TableName + ', ' + #prefix + #TableIdName + ' FROM ' + #TableName)
DECLARE #rTableName nvarchar(50)
DECLARE #rpk nvarchar(50)
DECLARE #rprefix nvarchar(3)
DECLARE #row INT
DECLARE #getRow CURSOR
SET #getRow = CURSOR FOR
SELECT DISTINCT(rid)
FROM #temptable
OPEN #getRow
FETCH NEXT
FROM #getRow INTO #row
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #row
SELECT #rTableName = rTableName FROM #temptable WHERE rid = #row
SELECT #rpk = rpk FROM #temptable WHERE rid = #row
SELECT #rprefix = rprefix FROM #temptable WHERE rid = #row
EXEC ('UPDATE ' + #rTableName + ' SET CoiRef = ' + #rprefix + '_' + #row + ' WHERE ' + #rpk + ' = ' + #row)
FETCH NEXT
FROM #getRow INTO #row
END
CLOSE #getRow
DEALLOCATE #getRow
FETCH NEXT
FROM #getTable INTO #table
END
CLOSE #getTable
DEALLOCATE #getTable
I have also tried another solution using sp_executesql but get similar errors there, this was using the below code instead on the first EXEC..
DECLARE #sqlCommand nvarchar(500)
SET #sqlCommand = 'INSERT INTO #temptable SELECT TableIdName, TableName, prefix, TableIdName FROM' + #TableName
EXECUTE sp_executesql #sqlCommand, N'#temptable nvarchar(50) output', #temptable OUTPUT
Again, Any help would be greatly appreciated..
Thanks..
Gerry
I think the error is coming from the fact that you're trying to use a table variable inside of dynamic sql. This is not something that is supported because the table variable is out of scope for the dynamic sql. You should make your #temptable into a temporary table using the create table command.
In the unsolicited advice category, I'd suggest attempting to recreate this without using cursors if at all possible, as cursors go against the concept of set based processing which is the foundation of sql server.

How to Loop table creation

I have the following code which works fine for one table but I am trying to figure out how to make it loop.
DECLARE #sql NVARCHAR(2000)
DECLARE #table VARCHAR(100)
DECLARE #command NVARCHAR(1000)
SELECT #table = ( VV.SRC_CD )
FROM VV
SET #sql = 'SELECT [CD],[SRC_CD],[SRC_CD_DESC],[DSC],[REFRESH_DT],[GEN_DSC] = CAST(null as VARCHAR(50)) INTO dbo.vv_' + #table
+
' FROM [vv] A WHERE A.SRC_CD <> ''GEN'' AND A.DSC <> ''NO DATA'' AND A.DSC <> ''(BLANK) NO'' AND A.src_cd = '''
+ #table + ''''
EXEC Sp_executesql
#stmt = #sql
The code that populates the #table variable returns one row. What I am trying to do is get this procedure to loop one time for each distinct value in the table for that row. The distinct clause doesn't work here and I have tried a basic table array with no luck.
Do I need to modify this to use a cursor?
It sounds like you're in need of a cursor, something like:
DECLARE #Iterator NVARCHAR(100)
,#sql NVARCHAR(MAX)
DECLARE xyz CURSOR
FOR
--Select stuff to iterate over
SELECT DISTINCT SRC_CD
FROM w
OPEN xyz
FETCH NEXT FROM xyz
INTO #Iterator
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff
SET #sql = 'SELECT [CD],[SRC_CD],[SRC_CD_DESC],[DSC],[REFRESH_DT],[GEN_DSC] = CAST(null as VARCHAR(50))
INTO dbo.vv_' + #Iterator +'
FROM [vv] A
WHERE A.SRC_CD <> ''GEN''
AND A.DSC <> ''NO DATA''
AND A.DSC <> ''(BLANK) NO''
AND A.src_cd = ''' + #Iterator + ''''
PRINT (#sql)
FETCH NEXT FROM xyz
INTO #Iterator
END
CLOSE xyz
DEALLOCATE xyz
GO
I left PRINT in there so you can ensure the output is as desired before executing.

INSERT INTO command doesn't work

I have one outer cursor and one inner cursor also have two tables to work with. Now with the outer cursor i'm making new columns in the table 1 and naming them by the values from the table two, and that works just fine. Problem is with the inner cursor witch i used to insert the values into those new columns from one specific column from another table. This seams not to work, but what confusing me is that i do not get any error messages. Now i hope you understand what i'm trying to do, here is the code so comment for more description about the problem :
DECLARE #rbr_param nvarchar(255)
DECLARE #vrednost nvarchar(255)
DECLARE #cName nvarchar(255)
DECLARE #sql nvarchar (255)
DECLARE curs CURSOR FOR SELECT DISTINCT rbr_param FROM dbo.parametri_pomocna ORDER BY rbr_param
OPEN curs
FETCH NEXT FROM curs
INTO #rbr_param
WHILE ##FETCH_STATUS = 0
BEGIN
SET #cName = 'P_'+#rbr_param+'_P'
EXEC('ALTER TABLE dbo.Parametri ADD ' + #cName + ' nvarchar(255)')
DECLARE vrd CURSOR FOR SELECT DISTINCT vrednost FROM dbo.parametri_pomocna
OPEN vrd
FETCH NEXT FROM vrd
INTO #vrednost
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'INSERT INTO dbo.Parametri'+(#cName)+ ' SELECT vrednost FROM dbo.parametri_pomocna WHERE vrednost = '+#vrednost+ ' AND rbr_param = '+#rbr_param
if exists (select * from INFORMATION_SCHEMA.COLUMNS where table_name = 'dbo.Parametri' and column_name = '#cName')
begin
exec(#sql)
end
FETCH NEXT FROM vrd
INTO #vrednost
END --end vrd
CLOSE vrd
DEALLOCATE vrd
FETCH NEXT FROM curs
INTO #rbr_param
END
CLOSE curs
DEALLOCATE curs
You have two problems here:
if exists ( select * from INFORMATION_SCHEMA.COLUMNS
where table_name = 'dbo.Parametri'
and column_name = '#cName'
)
(1) This view will never have table_name = schema name and table name.
(2) You have enclosed your variable name in single quotes for some reason.
For both of these reasons, your IF condition will never return true.
Try:
IF EXISTS
(
SELECT 1 FROM sys.columns
WHERE [object_id] = OBJECT_ID('dbo.Parametri')
AND name = #cName
)
(And here is why I prefer catalog views over INFORMATION_SCHEMA.)
Also this double-nested cursor thing seems quite inefficient and a lot more code than necessary to achieve what I think you're trying to do. How about something like this instead:
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'ALTER TABLE dbo.Parametri ADD '
+ QUOTENAME('P_' + rbr_param + '_P') + ' NVARCHAR(255);'
FROM dbo.parametri_pomocna GROUP BY rbr_param;
EXEC sp_executesql #sql;
SET #sql = N'';
SELECT #sql = #sql + N'INSERT dbo.Parametri('+QUOTENAME('P_' + rbr_param + '_P')+ ')
SELECT vrednost
FROM dbo.parametri_pomocna WHERE rbr_param = ''' + rbr_param + '''
GROUP BY vrednost;'
FROM dbo.parametri_pomocna
GROUP BY rbr_param;
EXEC sp_executesql #sql;

How to get the row count for views from a database?

I'm trying to make a customized view that gets me the row count for all the views and tables of a database.
Getting the count of table is damn in SQL Server
SELECT TABLE_SCHEMA,
TABLE_NAME = TABLES.TABLE_NAME,
RECORD_COUNT = MAX(SYSINDEXES.ROWS)
FROM SYS.SYSINDEXES "SYSINDEXES",
INFORMATION_SCHEMA.TABLES "TABLES"
WHERE TABLES.TABLE_NAME = OBJECT_NAME(SYSINDEXES.ID)
AND TABLES.TABLE_TYPE = 'BASE TABLE'
GROUP BY TABLES.TABLE_SCHEMA,
TABLES.TABLE_NAME
Now, I need to get the rowcount for VIEWS
I feel the only way is to count the number of rows from the views
i.e. count(*) from view_name
But, I could not find a way to have the rowcount for view along with view_name, table_schema and so on.
Any advance on this would be helpful.
Well, it isn't very pretty, but this should do the trick.
This applies to a single database because I'm using the system view 'all_views' to get the data. I'm sure it could be adapted if you wanted something else.
I've also limited the views I'm returning counts for, via the 'schema_id'. You can look at this and determine what would be best for you.
Lastly, I've just spit the results out so that you can view them if you run this in Management Studio. You would probably want to insert the results into a table or something instead. If so, it's simply a matter of changing the dynamic query from a select to an insert.
So without further adieu:
SET NOCOUNT ON
DECLARE #ViewName AS nVarChar(128)
, #Query AS nVarChar(500)
/* Declare Cursor */
DECLARE Cur_Views CURSOR
FOR
SELECT name
FROM [sys].[all_views] x
WHERE x.schema_id = 1
-- Loop through the views.
OPEN Cur_Views
-- Fetch the first view
FETCH NEXT FROM Cur_Views
INTO #ViewName
WHILE ##Fetch_Status = 0 BEGIN
-- Set up our dynamic sql
SELECT #Query = 'SELECT COUNT(*) AS [Count] FROM ' + #ViewName
-- Print the query we're executing for debugging purposes
-- PRINT #Query
-- Execute the dynamic query
EXECUTE(#Query)
-- Fetch subsequent views
FETCH NEXT FROM Cur_Views
INTO #ViewName
-- Loop back to the beginning
END -- WHILE ##Fetch_Status = 0 BEGIN
-- Close the cursor
CLOSE Cur_Views
-- Dispose of the cursor
DEALLOCATE Cur_Views
GO
Here , is the final solution:
SET NOCOUNT ON
DECLARE #ViewName AS nVarChar(128)
, #TmpQuery AS nVarChar(500)
, #Out3 as int
DECLARE Cur_Views CURSOR FOR
SELECT schema_name(schema_id)+'.'+name as "Table_Name" FROM [sys].[all_views]
OPEN Cur_Views
FETCH NEXT FROM Cur_Views INTO #ViewName
WHILE ##Fetch_Status = 0 BEGIN
--SELECT #Query = 'SELECT COUNT(*) AS [Count] FROM ' + #ViewName
--EXECUTE(#Query)
CREATE TABLE #Data (var int)
SELECT #TmpQuery = 'SELECT COUNT(*) AS [Count] FROM ' + #ViewName
INSERT #Data exec (#TmpQuery)
SELECT #Out3 = var from #Data
--PRINT #ViewName
--PRINT #Out3
insert into Person.ViewCountTracker values(#ViewName,#Out3)
DROP TABLE #Data
FETCH NEXT FROM Cur_Views INTO #ViewName
END
CLOSE Cur_Views
DEALLOCATE Cur_Views
GO
--create table Person.ViewCountTracker
--(
-- ViewName varchar(255),
-- RowValue int
--)
--select * from Person.ViewCountTracker
I know this is an old post and I do not intend to take credit from the marked answer but wanted to add to it.
SELECT #Query = 'SELECT ''' + #ViewName + ''' AS Name, COUNT(*) AS [Count] FROM ' + #ViewName
I added the View name to help distinguish the numbers more.
SET NOCOUNT ON
DECLARE #ViewName AS nVarChar(128), #TmpQuery AS nVarChar(384)
CREATE TABLE #Results (Name nVarChar(128), Cnt BigInt)
DECLARE Cur_Views CURSOR FOR SELECT schema_name(schema_id) + '.' + name AS Name FROM [sys].[all_views] WHERE is_ms_shipped = 0
OPEN Cur_Views
WHILE (1=1)
BEGIN
FETCH NEXT FROM Cur_Views INTO #ViewName
If ##Fetch_Status != 0 BREAK
SELECT #TmpQuery = 'SELECT ''' + #ViewName + ''' AS Name, COUNT_BIG(*) AS Cnt FROM ' + #ViewName + ' (NoLock)'
PRINT #TmpQuery
INSERT #Results EXEC (#TmpQuery)
END
CLOSE Cur_Views
DEALLOCATE Cur_Views
SET NOCOUNT OFF
SELECT * FROM #Results
DROP TABLE #Results
GO

Execute a Stored Procedure in a SELECT statement

For an instance I a select statement and it is returning 1000 rows. I need to execute a particular stored procedure for every row the the select statement is returning.
have you got any idea how can I do that?
Construct the EXECUTE statements in your select like this:
SELECT 'EXEC sp_whatever ' + parameter stuff
FROM your_table
Then run the results! Alternatively, paste your results into a spreadsheet package, and use string concatenation to construct the EXEC statements - just create a formula and paste it down the 1,000 rows. I personally prefer the first approach.
To clarify the "parameter stuff", take the example of a stored procedure that takes two int parameters that you want to take from columns you your_table. You'd then have something like this:
SELECT 'EXEC sp_whatever ' + CAST(field1 AS varchar) + ', ' + CAST(field2 AS varchar)
FROM your_table
Not the need to be careful with string fields here - you run the risk of inadvertently exposing yourself to your own SQL injection attack, as with any SQL string concatenation.
I am reading your "for an instance" as "this is a one-off task". If this is a task that needs automating, then one of the other answers may be the right approach.
You can do it like this:
declare #execstatementsbatch nvarchar(max)
select #execstatementsbatch = ''
SELECT #execstatementsbatch = #execstatementsbatch + 'EXEC UpdateQty ' + ItemCode + ', ' + QtyBO + '; '
FROM ITEMSPO
INNER JOIN .....
<some conditions>
exec(#execstatementsbatch)
Disclaimer: I'm not sure if I understand your question correctly.
Assuming you are on SQL Server 2005 upwards, you could create a table-valued user defined function and use the OUTER APPLY operator in your query.
Most RDBMS will let you select rows from stored procedure result sets. Just put your stored procedures in the FROM clause, as you would for common table expressions. For instance:
SELECT sp.ColumnInResultSet, t.BaseTableColumnName
FROM sp_whatever ( Args) sp INNER JOIN BaseTable t ON t.ID = sp.ID;
CREATE PROCEDURE dbo.usp_userwise_columns_value
(
#userid BIGINT
)
AS
BEGIN
DECLARE #maincmd NVARCHAR(max);
DECLARE #columnlist NVARCHAR(max);
DECLARE #columnname VARCHAR(150);
DECLARE #nickname VARCHAR(50);
SET #maincmd = '';
SET #columnname = '';
SET #columnlist = '';
SET #nickname = '';
DECLARE CUR_COLUMNLIST CURSOR FAST_FORWARD
FOR
SELECT columnname , nickname
FROM dbo.v_userwise_columns
WHERE userid = #userid
OPEN CUR_COLUMNLIST
IF ##ERROR <> 0
BEGIN
ROLLBACK
RETURN
END
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #columnlist = #columnlist + #columnname + ','
FETCH NEXT FROM CUR_COLUMNLIST
INTO #columnname, #nickname
END
CLOSE CUR_COLUMNLIST
DEALLOCATE CUR_COLUMNLIST
IF NOT EXISTS (SELECT * FROM sys.views WHERE name = 'v_userwise_columns_value')
BEGIN
SET #maincmd = 'CREATE VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
ELSE
BEGIN
SET #maincmd = 'ALTER VIEW dbo.v_userwise_columns_value AS SELECT sjoid, CONVERT(BIGINT, ' + CONVERT(VARCHAR(10), #userid) + ') as userid , '
+ CHAR(39) + #nickname + CHAR(39) + ' as nickname, '
+ #columnlist + ' compcode FROM dbo.SJOTran '
END
--PRINT #maincmd
EXECUTE sp_executesql #maincmd
END
-----------------------------------------------
SELECT * FROM dbo.v_userwise_columns_value