How to store a query result in a variable - sql

SQL Server stored procedure:
CREATE PROCEDURE [dbo].[CheckTableStatus]
#DatabaseName AS NVARCHAR(50) = 'DBA',
#ProjectID AS NVARCHAR(50) = 'CommandLog'
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TableCount as int
SET #Temp = 'DECLARE #cnt as int;'
SET #Temp = #Temp + 'USE '+ #DatabaseName +'; SELECT #cnt=COUNT(TABLE_NAME) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_NAME=''' + #ProjectID + ''';'
PRINT #Temp
EXEC sp_executesql #temp
--ASSIGN OUTPUT TO #TableCount
IF #TableCount > 0
-- Do something
END
How do I assign the results of #temp being executed to variable #TableCount?

If your goal is to get the count from #temp, try using an OUTPUT with your dynamic SQL:
EXEC sp_executesql #temp, N'#cnt int OUTPUT', #TableCount OUTPUT
These additions to sp_executesql will output the #cnt value in your dynamic SQL to the #TableCount in your current context.

Use the OUTPUT parameter:
CREATE PROCEDURE [dbo].[CheckTableStatus]
#DatabaseName as nvarchar(50) = 'DBA',
#ProjectID as nvarchar(50) = 'CommandLog'
AS
BEGIN
SET NOCOUNT ON;
DECLARE #TableCount as int,#Temp nvarchar(max)='';
-- SET #Temp = 'DECLARE #cnt as int;'
SET #Temp = #Temp + 'USE '+ #DatabaseName +'; SELECT #cnt=COUNT(TABLE_NAME) FROM INFORMATION_SCHEMA.Tables WHERE TABLE_NAME=''' +
#ProjectID + ''';'
print #Temp
EXEC sp_executesql #temp,
N'#cnt int out',#TableCount out;
--ASSIGN OUTPUT TO #TableCount
IF #TableCount >0
-- Do something
print #TableCount;
END
But why not use the OBJECT_ID function?
Also your code is prone to SQL-injection.

You can set value as
SET #TableCount = #cnt

Related

Dynamically Creating a table and inserting Rows inside a SP

I am trying to run a Stored Procedure that Inserts into a Table.
I keep getting the Incorrect syntax near 'tbl_1_2'.
It doesn't Insert the data.I am using MSSQL2012
Alter PROCEDURE [dbo].[TT] AS
BEGIN
declare #tbl varchar(100);
set #tbl='tbl_1_2';
declare #sql varchar(100);
DECLARE #ptablename VARCHAR(max) = (#tbl)
set #ptablename=#tbl
SET #sql = 'INSERT INTO ' + #ptablename ;
EXEC (#sql)
select *
from (
values('1','2')
) t1 (c1, c2)
End
See this sample and compare with your code to understand your error.
Create Table Test (ID int, Name sysname)
Go
Declare #TableName sysname = 'Test'
DECLARE #ID int = 1
DECLARE #Name sysname = 'Meysam'
Declare #SQL nVarchar(4000) = 'INSERT #TableName (ID, Name) Values (#ID, N''#Name'')'
Set #SQL = REPLACE(#SQL, '#TableName', #TableName)
Set #SQL = REPLACE(#SQL, '#ID', #ID)
Set #SQL = REPLACE(#SQL, '#Name', #Name)
EXEC (#SQL)
SELECT * FROM Test

SQL Server Default Column value from function

I want to set default value to Id column in Person table with a function
that goes like this:
Function:
IF OBJECT_ID ( 'GetLastId','FN') IS NOT NULL
DROP function GetLastId;
GO
CREATE FUNCTION [dbo].[GetLastId]
(#TableName nvarchar(max))
RETURNS int
AS
BEGIN
DECLARE #LastId int;
DECLARE #sql nvarchar(max);
SET #sql = 'SELECT #LastId = ISNULL(MAX(Id), 0) + 1 FROM ' + #TableName + ';'
EXECUTE sp_executesql #sql, N'#LastId int output', #LastId = #LastId output;
RETURN #LastId
END
and then:
UPDATE Person
SET Id = dbo.GetLastId('Person')
Running this code throws an error:
Only functions and some extended stored procedures can be executed from within a function.
So how to fix this and make it work as a default value?
And please do not say "Use triggers..." as I intend to use it with Entity Framework Core as default value for primary keys.
Thanks
You want a stored procedure, not a function:
create procedure [dbo].[GetLastId] (
#TableName nvarchar(max),
#LastId int output
) as
begin
declare #sql nvarchar(max);
set #sql = 'select #LastId = ISNULL(MAX(Id), 0) + 1 from ' + #TableName + ';'
EXECUTE sp_executesql #sql,
N'#LastId int output',
#LastId=#LastId output;
end;
You should also use quotename() around the table name to prevent unexpected things from happening.
Then you would call this as:
declare #lastId int;
exec dbo.GetLastId('Person', #lastid output);
update Person
set Id = #lastId;
You need to create stored procedure instead of function
create procedure [dbo].[GetLastId] (
#TableName nvarchar(max),
#ColumnName nvarchar(200),
#LastId int output
) as
begin
declare #sql nvarchar(max);
set #sql = 'select #LastId = ISNULL(MAX('+ #ColumnName +'), 0) + 1 from ' + #TableName + ';'
EXECUTE sp_executesql #sql,
N'#LastId int output',
#LastId=#LastId output;
end;
Then you can execute sp like below
declare #lastId int
exec dbo.GetLastId 'Person', 'Id' , #lastid output;
select #lastId
update Person
set Id = #lastId;

Compare two table using dynamic database

I have 2 table (same name) on 2 different database
I want compare these table, this is my procedure
ALTER PROCEDURE COUNTCOLUMN
#TABLENAME NVARCHAR(MAX),
#DATABASENAME1 NVARCHAR(MAX),
#DATABASENAME2 NVARCHAR(MAX)
AS
BEGIN
DECLARE #COLNAME NVARCHAR(MAX)
DECLARE #ROWCOUNT INT
DECLARE #ROWCOUNT2 INT
DECLARE #NUMB1 INT
DECLARE #NUMB2 INT
DECLARE #SQLQUERY NVARCHAR(MAX)
DECLARE #SQLQUERY2 NVARCHAR(MAX)
DECLARE #SQLQUERY3 NVARCHAR(MAX)
DECLARE #SQLQUERY4 NVARCHAR(MAX)
DECLARE #SQLQUERY5 NVARCHAR(MAX)
DECLARE #SQLQUERY6 NVARCHAR(MAX)
SET #SQLQUERY = 'SELECT #NUMBER = COUNT(*) FROM information_schema.columns WHERE table_name = '+N'#TESTTB'+''
SET #SQLQUERY2 = 'USE ' + #DATABASENAME1
SET #SQLQUERY3 = 'USE ' + #DATABASENAME2
EXECUTE sp_executesql #SQLQUERY2
EXECUTE sp_executesql #SQLQUERY, N'#TESTTB NVARCHAR(MAX), #NUMBER INT OUTPUT',#TESTTB = #TABLENAME ,#NUMBER = #NUMB1 OUTPUT
EXECUTE sp_executesql #SQLQUERY3
EXECUTE sp_executesql #SQLQUERY, N'#TESTTB NVARCHAR(MAX), #NUMBER INT OUTPUT',#TESTTB = #TABLENAME ,#NUMBER = #NUMB2 OUTPUT
IF(#NUMB1 <= #NUMB2)
BEGIN
DECLARE #NUMB INT
SET #NUMB = 1
WHILE (#NUMB <= #NUMB1)
BEGIN
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'TEMP1'))
BEGIN
DROP TABLE TEMP1
END
IF (EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'TEMP2'))
BEGIN
DROP TABLE TEMP2
END
ELSE
BEGIN
SET #SQLQUERY4 = 'SELECT #COL_NAME = COL_NAME(OBJECT_ID(#TABLENAME), #NUMB)'
EXECUTE sp_executesql #SQLQUERY2
EXECUTE sp_executesql #SQLQUERY4, N'#TABLENAME NVARCHAR(MAX),#NUMB INT, #COL_NAME NVARCHAR(MAX) OUTPUT', #TABLENAME = #TABLENAME,#NUMB=#NUMB, #COL_NAME = #COLNAME OUTPUT
SET #SQLQUERY5 = 'SELECT '+ #COLNAME + ' INTO TEST_DB..TEMP1 FROM ' + #TABLENAME
EXECUTE sp_executesql #SQLQUERY2
EXECUTE sp_executesql #SQLQUERY5
EXECUTE sp_executesql #SQLQUERY3
EXECUTE sp_executesql #SQLQUERY4, N'#TABLENAME NVARCHAR(MAX),#NUMB INT, #COL_NAME NVARCHAR(MAX) OUTPUT', #TABLENAME = #TABLENAME,#NUMB=#NUMB, #COL_NAME = #COLNAME OUTPUT
SET #SQLQUERY6 = 'SELECT ' + #COLNAME +' INTO TEST_DB..TEMP2 FROM '+ #TABLENAME
EXECUTE sp_executesql #SQLQUERY3
EXECUTE sp_executesql #SQLQUERY6
SELECT #ROWCOUNT = COUNT(*) FROM TEMP1
SELECT #ROWCOUNT2 = COUNT(*) FROM TEMP2
IF(#ROWCOUNT != #ROWCOUNT2)
BEGIN
PRINT N'NUMBER OF ROWS ARE NOT EQUAL';
BREAK
END
ELSE IF (#NUMB > #NUMB1)
BREAK
ELSE
BEGIN
SELECT * FROM TEST_DB..TEMP1
EXCEPT
SELECT * FROM TEST_DB..TEMP2
SET #NUMB = #NUMB + 1;
CONTINUE
END
END
END
END
END
It should be like this TEMP1 <--TEST_DB..TESTTABLE, TEMP2 <--TEST_DB2..TESTTABLE
But TEMP1 , TEMP2 always have the same values as TESTTABLE from the first database (TEST_DB )
It seem like I can't switch between two databases in procedure so I try to run it separate but still not work

dynamic column name in sql server 2008 in stored procedure

Can I use the following syntax in stored procedure,
set #count = (select count(*) from [dbo].[employee] where #column_name ='T')
CREATE PROCEDURE Proc_Name
#Column_Name NVARCHAR(128),
#COUNT INT OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N'SELECT #count = count(*) from [dbo].[employee] where ' + QUOTENAME(#Column_Name)
+ N' =''T'''
EXECUTE sp_executesql #Sql
,N'#COUNT INT OUTPUT'
,#COUNT OUTPUT
END

MS SQL Stored Procedure for counting Dynamic table items

I had wrote this below stored procedure and getting incorrect statement.
ALTER PROCEDURE dbo.[Counter]
#TableName VARCHAR(100)
AS
BEGIN
DECLARE #Counter INT
DECLARE #SQLQ VARCHAR(200)
SET NOCOUNT ON;
--SET #TableName = 'Member';
SET #SQLQ = 'SELECT COUNT(*) FROM dbo.[' + #TableName + ']';
--Preparing the above sql syntax into a new statement(get_counter).
--Getting an error here I had googled the prepare statement but don't know why facing this error.
PREPARE get_counter FROM #SQLQ;
#Counter = EXEC get_counter; -- here #resutl gets the value of the count.#TableName
DEALLOCATE PREPARE get_counter; -- removing the statement from the memory.
END
Then I had wrote another one:
ALTER PROCEDURE dbo.[Counter]
#TableName VARCHAR(100)
AS
BEGIN
DECLARE #Counter INT
DECLARE #SQLQ VARCHAR(200)
SET NOCOUNT ON;
--SET #TableName = 'Member';
SET #SQLQ = 'SELECT COUNT(*) FROM dbo.[' + #TableName + ']';
--Preparing the above sql syntax into a new statement(get_counter).
Execute #SQLQ; -- here #resutl gets the value of the count.#TableName
--DEALLOCATE PREPARE get_counter; -- removing the statement from the memory.
Return #Counter;
END
It is running fine but I can't get the result in the Counter , anyone please help me(I know that I haven't assigned any value to the counter but if I do I get error).
After your answer martin I had replace my code with yours now its :
ALTER PROCEDURE dbo.[Counter] #SchemaName SYSNAME = 'dbo' , #TableName SYSNAME
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLQ NVARCHAR(1000)
DECLARE #Counter INT;
SET #SQLQ = 'SELECT #Counter = COUNT(*) FROM ' +
Quotename(#SchemaName) + '.' + Quotename(#TableName);
EXEC sp_executesql
#SQLQ ,
N'#Counter INT OUTPUT',
#Counter = #Counter OUTPUT
Return SELECT #Counter
END
Now I had retrieved it .
ALTER PROCEDURE dbo.[CreateBusinessCode]
#MemberID bigint,
#len int,
#RewardAccountID bigint,
#ConnectionStatusID tinyint,
#Assign smalldatetime
AS
BEGIN
SET NOCOUNT ON;
DECLARE #counter INT
EXEC #counter = dbo.Counter 'dbo','member';
Select #counter;
END
You should use SYSNAME for object identifiers and Quotename rather than concatenating the square brackets yourself.
ALTER PROCEDURE dbo.[Counter] #TableName SYSNAME,
#SchemaName SYSNAME = 'dbo'
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLQ NVARCHAR(1000)
DECLARE #Counter INT;
SET #SQLQ = 'SELECT #Counter = COUNT(*) FROM ' +
Quotename(#SchemaName) + '.' + Quotename(#TableName);
EXEC sp_executesql
#SQLQ ,
N'#Counter INT OUTPUT',
#Counter = #Counter OUTPUT
SELECT #Counter
END
In SQL Server, if you want to get a result into a variable, you have two choices.
The first is to use cursors.
The second is to do dynamic SQL:
declare #sql varchar(max) = whatever;
declare #cnt int;
declare #cntTable table as (cnt int);
insert into #cntTable
exec(#sql);
select #cnt = t.cnt
from #cntTable
It is cumbersome, but one or the other does work.
try this one.It doesnt query the actual table but will provide you the count of rows.This is better way if you have large tables and you need approximate count.
ALTER PROCEDURE dbo.[Counter]
#TableName VARCHAR(100)
AS
begin
declare #objectid int,#counter int
select #objectid = object_id from sys.all_objects where name = #tablename and schema_id=SCHEMA_ID('dbo')
select #counter = sum(rows) from sys.partitions where object_id= #objectid
and index_id in (0,1)
select #counter
end
go