Using sp_executesql without returning row sets - sql

In a store procedure I am building dynamic SQL statement which is executed using sp_executesql procedure.
The dynamic SQL statement can be a store procedure, that:
do not return row set
do return one row set
do return multiple row sets
The initial store procedure itself returns other row sets. I want to return only them, and to not return the row sets from the internal procedure.
Generally, I want to force the following statement to do not return anything:
DECLARE #DynamicSQLStatement NVARCHAR(MAX)
SET #DynamicSQLStatement = N'SELECT 1 SELECT 2 SELECT 3 SELECT 4 SELECT 5'
EXEC sp_executesql #DynamicSQLStatement
Is there a way to do this?

I guess you can tweak your Store Procedures by doing something like this .
CREATE PROCEDURE usp_StopMessageProc
#StopMsg bit = 0
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql VARCHAR(MAX);
SET #Sql = '';
SET #Sql = 'SELECT Column1, Column2, Column3.... ';
IF #StopMsg = 1
SET #Sql = #Sql + 'INTO #TempDeleteMe';
SET #Sql = #Sql +
'FROM dbo.SomeTable ';
EXEC(#Sql);
END
GO
By defualt your proc will do whatever it does best but when #StopMsg is set to 1 it suppress the return messages/Result sets.

Related

SQL Server - Assign value to variable inside Dynamic SQL

I wanted to assign value to out variable inside a dynamic query.
SET #query = 'IF EXISTS(Condition)
BEGIN
--Some action goes here
SET #result= 1
END
ELSE
BEGIN
SET #result= 2
END'
EXEC(#query)
When am trying to execute this query, I am getting an error:
Must declare the scalar variable "#result".
How can I set value to variable inside dynamic query?
Thanks in advance.
Just try this:
DECLARE #result INT
,#query NVARCHAR(MAX);
SET #query = 'IF (1 = 0)
BEGIN
--Some action goes here
SET #result= 1
END
ELSE
BEGIN
SET #result= 2
END';
EXEC sp_executesql #query, N'#result INT OUTPUT',#result = #result OUTPUT
SELECT #result;
You can use sp_executesql in order to execute dynamic T-SQL statement and initialize SQL variables. In the sp_executesql you need to pass the parameter definition and then parameter mappings.
When you Execute a Query String, It is Considered as a separate session, so The variables that you have declared in the current windows won't be accessible whereas you can access the Temporary tables.
So you have to declare the variable inside the string. Your Query can be re-written as below
SET #query = '
DECLARE #result INT
IF EXISTS(Condition)
BEGIN
--Some action goes here
SET #result= 1
END
ELSE
BEGIN
SET #result= 2
END'
EXEC(#query)
Or Store the result in a table variable and access it from there
DECLARE #Tablevar TABLE
(
Result INT
)
SET #query = '
IF EXISTS(Condition)
BEGIN
--Some action goes here
select 1
END
ELSE
BEGIN
SELECT 2
END'
INSERT INTO #Tablevar
EXEC(#query)
select #Result = Result FROM #Tablevar

Returning passed parameter as column in result set

I have the following stored procedure code working and want to add the passed parameter #tabname as a column in the result set.
CREATE PROCEDURE CountStar
#Tabname char(10)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL varchar(250)
SELECT #SQL = 'SELECT ETL_LAST_UPD_DTTM, COUNT(*) FROM ls.' + QuoteName(#Tabname) +
'GROUP BY ETL_LAST_UPD_DTTM'
EXEC (#SQL)
SELECT #SQL = 'SELECT ETL_LAST_UPD_DTTM, COUNT(*) FROM ci.' + QuoteName(#Tabname) +
'GROUP BY ETL_LAST_UPD_DTTM'
EXEC (#SQL)
--COMMIT
END
GO
Currently this will return the last updated timestamp and the record count for the table being passed into the stored procedure for the 2 schemas identified. I want to add the #tabname to the result set as the first column followed by last updated timestamp and the record counts. This returns 2 result sets and each should look something like this for each returned result set.
Table_name Timestamp rec_cnt
--------------------------------------------------
CUSTOMERS 2015-09-24 13:10:01.1770000 378
I have tried a few things but can't get the syntax correct.
Thanks for any pointers.
Pat
CREATE PROCEDURE CountStar
#Tabname SYSNAME --<-- use appropriate data type for sql server objects
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL nvarchar(max);
SELECT #SQL = N'SELECT #Tabname AS Table_name,ETL_LAST_UPD_DTTM, COUNT(*)
FROM ls.' + QuoteName(#Tabname) +
N' GROUP BY ETL_LAST_UPD_DTTM'
EXEC sp_executesql #SQL
,N'#Tabname SYSNAME'
,#Tabname
SELECT #SQL = N'SELECT #Tabname AS Table_name,ETL_LAST_UPD_DTTM, COUNT(*)
FROM ci.' + QuoteName(#Tabname) +
N' GROUP BY ETL_LAST_UPD_DTTM'
EXEC sp_executesql #SQL
,N'#Tabname SYSNAME'
,#Tabname
END
GO

SQL "if exists..." dynamic query

Suppose I have a query stored in a variable like this (it's actually dynamically populated and more complex, but this is for demonstration purposes):
DECLARE #Query VARCHAR(1000) = 'SELECT * FROM dbo.MyTable'
Is there a way to check if the query would return any results? Something like this, but this doesn't work:
IF EXISTS (#Query)
BEGIN
-- do something
END
The only way that I can think of to do this is to put the results in a temp table and then query from that, but that is not ideal because the columns in the dynamic query can vary and I really don't need the temp table at all for any reason other than checking whether some rows would be returned. Is there a better way?
Try Executing the Dynamic query and use ##RowCount to find the existence of rows.
DECLARE #Query NVARCHAR(1000) = 'SELECT * FROM [dbo].[Mytable]',
#rowcnt INT
EXEC Sp_executesql #query
SELECT #rowcnt = ##ROWCOUNT
IF #rowcnt > 0
BEGIN
PRINT 'row present'
END
Try this:
DECLARE #Query NVARCHAR(1000) = 'SELECT #C = COUNT(*) FROM dbo.MyTable'
DECLARE #Count AS INT
EXEC sp_executesql #Query, N'#C INT OUTPUT', #C=#Count OUTPUT
IF (#Count > 0)
BEGIN
END
I know this answer is too late. but, I'm leaving this here to help someone else to use IF EXISTS with a dynamic query.
This is how you should do it with dynamic queries.
DECLARE #Query VARCHAR(MAX)
SET #Query = 'SELECT * FROM [dbo].[MyTable]'
SET #Query = 'IF EXISTS (' + #Query + ')
BEGIN
-- do something
print ''1''
END
ELSE
BEGIN
-- do something else
print ''0''
END
'
exec (#Query)
Hope this helped someone. Vote if it did :)
You can use EXEC to execute sql statement, then call ##ROWCOUNT which Returns the number of rows affected by the last statement, to check row exists in sql select stetement.
DECLARE #Query VARCHAR(1000) = 'SELECT * FROM dbo.MyTable',#hasRow int
EXEC (#Query)
SELECT #hasRow =##ROWCOUNT // Returns the number of rows affected by the last statement
PRINT #hasRow
IF #hasRow > 0
BEGIN
Print 1
END
BEGIN
Print 2
END
Hi I think that only way is to put IF EXISTS part into code of execution. My case is to stop execution in point when select affects at least one row, that is goal of IF EXISTS.
Little example that saves reading all records covering by condition to first occurence:
set nocount off;
drop table if exists #temp
go
create table #temp (idCol int identity(1,1),someText nvarchar(1))
go
insert into #temp values ('a')
go 25000
declare #query nvarchar(max)
,#resultFork bit
set #query = 'if exists (select * from #temp where idCol % 3 = 0)
set #resultFork=1
else
set #resultFork=0'
print #query
exec sp_executeSQL #query, N'#resultFork int output', #resultFork=#resultFork output
print #resultFork
/*Now U can use #resultFork in simple if condition...
if #resultFork = 1
begin
--
end
else
begin
--
end
*/

Stored procedure: how to use column as an input

I'm trying to create a simple stored procedure to count the number of empty records in my database:
CREATE PROCEDURE dbo.cnt_empty
#col NVARCHAR(10)
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT ON;
SELECT COUNT(#col) AS cnt
FROM dbo.mytable
WHERE #col = ''
END
GO
EXECUTE dbo.cnt_empty #col = N'field1' -- nvarchar(10)
I returns 0 for all the columsn I tested. What is wrong with this procedure?
Your string is not being assessed as the column name, so you are actually running "where 'field1' = ''"
You need to do something like this
set #sql = 'select #cnt = COUNT(*) from [' + #tableSchema + '].[' + #tableName +
'] where [' + #columnName + '] is not null';
-- print #sql; --uncomment for debugging
exec sp_executesql #sql, N'#cnt bigint output', #cnt = #cnt output;
Look at http://blog.hoegaerden.be/2009/02/15/script-find-all-empty-columns-in-database/ for the full script.
By doing this, your SQL statement is treating the parameter like a string, not like the name of a column. Take a look at sp_executesql. That will help you build up a SQL string and execute it.
you are matching #col (i.e. 'field1') against empty (i.e. '') in your where clause - that will never return a row.
What you want to do is declare a variable like #sql VARCHAR(500)
Then do
SET #sql = 'SELECT COUNT('+#col+') AS cnt FROM dbo.mytable'
Then try use the built in sp called sp_Executesql
http://msdn.microsoft.com/en-us/library/ms188001.aspx
This is because you are selecting the count of the variable not the count of the column.
Take a look at this article: http://www.mssqltips.com/sqlservertip/1160/execute-dynamic-sql-commands-in-sql-server/
Basically using EXEC statement or sp_executesql should be your choice.

How to return the rowcount of a dynamic sql query in SP?

I would like to return the rowcount of a dynamic sql query using linq similar to mentioned here:
http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx
I'm using dynamic sql to create the where clause and to implement paging on the result set, The rowcount I want to return is the total number of records that meet the where condition.
My SQL that is causing me problems:
-- get row count
SET #SQL = '#TotalRowCount = SELECT COUNT(*) as TotalRowCount'
SET #SQL = #SQL + #WHERE
IF (LEN(#SUBWHERE) > 0)
BEGIN
SET #SQL = #SQL + #SUBWHERE
END
SET #SQL = #SQL + ')) '
exec sp_executesql #SQL
END
(I need this to be the output param #TotalRowCount in the param list here):
ALTER PROCEDURE [dbo].[_tournament_GetTournamentsByConveners]
(
#LastName varchar(100) = null ,
#Username varchar(256) = null ,
#Email varchar(100) = null ,
#IsWildcard bit = null,
#PageIndex int ,
#PageSize int,
#TotalRowCount int output
)
AS
This is by design.
The scope of the #TotalRowCount in the dynamic SQL is different to the scope of #TotalRowCount declared in the stored procedure. That is, the dynamic SQL has it's own scope.
If you insist on using dynamic SQL, do this to add the total rows to the record set that is returned
SELECT col1, col2,
COUNT(*) OVER () AS TotalRows
FROM ...
Otherwise we only have partial code to offer any suggestions for improvement. You appear to have LINQ to call stored procs with execute dynamic SQL. This is too convoluted.
You can declare output parameters with sp_executesql. So to get your result alter the code as shown below.
Always be careful when concatenating SQL code like this as it is extremely vulnerable to SQL injection.
DECLARE #SQL nvarchar(4000)
SET #SQL = N'SELECT #TotalRowCount = COUNT(*) as TotalRowCount'
SET #SQL = #SQL + #WHERE
IF (LEN(#SUBWHERE) > 0)
BEGIN
SET #SQL = #SQL + #SUBWHERE
END
SET #SQL = #SQL + N')) '
exec sp_executesql #SQL, N'#TotalRowCount int output', #TotalRowCount output
you can also express this more compact as:
DECLARE #SQL nvarchar(4000)
SET #SQL = N'SELECT #TotalRowCount = COUNT(*) as TotalRowCount' + #WHERE + ISNULL(#SUBWHERE, N'') + N'))'
exec sp_executesql #SQL, N'#TotalRowCount int output', #TotalRowCount output