Can I use variable in condition statement as value with where condition that test that value - sql

I have the following stored procedure:
ALTER proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int
as
DECLARE #value nvarchar(10)
SET #value = 's'+CONVERT(nvarchar(50),#snum)
DECLARE #sqlText nvarchar(1000);
DECLARE #sqlText2 nvarchar(1000);
DECLARE #sqlText3 nvarchar(1000);
declare #g nvarchar(50) = '''g1'''
SET #sqlText = N'SELECT ' + #value + N' FROM dbo.GrideBtable'
SET #sqlText2 = ' where Gnumber = '+#g --here is the problem it error invalid column name -- the #g is value from the table condition
set #sqlText3 = #sqlText+#sqlText2
Exec (#sqlText3) -- here how can i save the result of the exec into varibale
declare #sal nvarchar(50) = #sqlText3
insert employ (name,Snumber,Gnumber,Salary) values(#name,#snum,#gnum,#sal)
QUESTION: How to put in condition variable gets value from the table when i exec it it think that the #g is column but its not its a value from the table to test it so i display one value after the exec the other QUESTION is how to save the result from the exec in variable and then use that value
I'm using SQL Server 2008 (9.0 RTM)
This will be a stored procedure
Thanks in advance

Not sure why you would go through all the loops to insert into the table where you can have a simple insert query like ..
ALTER PROC dbo.[insertperoll] #name nvarchar(50) , #snum int , #gnum int
AS
insert employ (name, Snumber, Gnumber, Salary)
select #name
, #sum
, #gnum
, case when #snum = 1 then s1
when #snum = 2 then s2
when #snum = 3 then s3
when #snum = 4 then s4
end as Salary
from dbo.GrideBtable
where Gnumber = #gnum

If your intent is to have the proc retrieve a salary value from a column determined from the parameter snum and then make an insert into employ using the values passed as parameters and the salary retrieved I think you could refactor your procedure to this:
CREATE proc [dbo].[insertperoll] #name nvarchar(50) , #snum int , #gnum int AS
DECLARE #g NVARCHAR(50) = 'g1'
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'INSERT employ (name,Snumber,Gnumber,Salary) '
SET #sql += N'SELECT ' + QUOTENAME(#name, '''')
SET #sql += N', ' + CAST(#snum AS NVARCHAR(50))
SET #sql += N', ' + CAST(#gnum AS NVARCHAR(50))
SET #sql += N', s' + CAST(#snum AS NVARCHAR(50))
SET #sql += N' FROM dbo.GrideBtable'
SET #sql += N' WHERE Gnumber = ' + QUOTENAME(#g, '''')
EXEC (#sql)
Of course you could add the #g variable to the procedure parameters instead of having it hard coded in the procedure and call it as:
EXEC insertperoll #name='john', #snum=10, #gnum=100, #g='g1'
Sample SQL Fiddle (with some assumptions made about table structure)

You could do this using sp_executesql instead of exec() since this will allow you to use parameters, you can use an output parameter to get the value from the query:
DECLARE #SQL NVARCHAR(MAX) = N'SELECT #val = ' + CONVERT(NVARCHAR(10),#snum) +
N' FROM dbo.GrideBtable WHERE Gnumber = #G1';
DECLARE #val INT; -- NOT SURE OF DATATYPE REQUIRED
EXECUTE sp_executesql #SQL, N'#G1 VARCHAR(20), #val INT OUT', 'G1', #val OUT;

Related

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;

Set declared parameter value and CONCAT column name

I have table with columns Char1, Char2, Char3..... Each of these columns contain some value. I declared variable #i and in while loop I'm trying to concat it to the Char table column name.
Also, I declared parameter #current in my query and then I'm trying to set its value in the query.
set #tmp = cast(#i as varchar(2))
select #current = 'Char' + #tmp
from SerialNumberFormat
where Example = 'XXXXXXXXXX'
When I execute the query #current has value Char1, Char2, Char3...etc, instead the value of the column.
How I can set column value instead column name in #current?
select #current = Concat(Char1, Char2, Char3)
from SerialNumberFormat
where Example = 'X59AA419010045'
Solution which I found and works for me is executing sp_executesql stored procedure
set #SQL = N'select #currentOUT = Char' + #tmp + ' from SerialNumberFormat
where Example = ''XXXXXXXXX'''
SET #ParmDefinition = N'#currentOUT nvarchar(10) OUTPUT'
exec sp_executesql #SQL, #ParmDefinition, #currentOUT = #current OUTPUT
select #current
Dynamic Sql like this may work for you
Declare #i int = 5
Declare #tmp varChar (10) = #i
Declare #Sql nVarChar(Max) = 'select Char' + #tmp + '
from SerialNumberFormat
where Example = ''X59AA419010045'''
exec sp_executesql #Sql

TSQL: Using 'Output' clause in dynamic SQL

I'm using an Output clause in my Insert statement which requires use of a Table Variable. I also want the Table name to be dynamic so I'm using dynamic SQL but it won't allow use of a Table Variable. I get the error Must declare the scalar variable "#InsertedId".
CREATE PROCEDURE sp_InsertPerson #Name varchar(50), #Table varchar(20) AS
DECLARE #InsertedId TABLE (Id int)
DECLARE #SQL nvarchar(200) = 'INSERT INTO ' + #Table + ' (Name) OUTPUT INSERTED.Id INTO ' + #InsertedId + ' VALUES (' + #Name + ')'
IF (#Name is not null AND #Name != '')
EXEC(#SQL)
SELECT Id FROM #InsertedId
How can I both use the Output clause and a dynamic Table name
First of all, do not use sp_ prefix to your stored procedure, cause it reserved to System stored procedures by MS, and can lead to performance issue and other problems (as it can be a habit). Use SysName datatype for the table name, and use QUOTENAME() function when you concatenate the string.
You need to declare your table in the DynamicSQL as
CREATE PROCEDURE InsertPerson
#Name varchar(50),
#Table SysName
AS
DECLARE #SQL NVARCHAR(MAX);
SET #SQL = N'DECLARE #IDs TABLE (ID INT);'+
'INSERT INTO ' +
QUOTENAME(#Table) +
' (Name) OUTPUT INSERTED.ID INTO #IDs VALUES(#Name);'+
'SELECT * FROM #IDs';
EXECUTE sp_executesql #SQL,
N'#Name VARCHAR(50)',
#Name;
Demo
Try this;
CREATE PROCEDURE sp_InsertPerson #Name varchar(50), #Table varchar(20) AS
DECLARE #SQL nvarchar(200) = ''
SET #SQL = #SQL + 'DECLARE #InsertedId TABLE (Id int)';
SET #SQL = #SQL + 'INSERT INTO ' + #Table + ' (Name) OUTPUT INSERTED.Id INTO #InsertedId (Id) VALUES (''' + #Name + ''')'
SET #SQL = #SQL + 'SELECT Id FROM #InsertedId'
IF (#Name is not null AND #Name != '')
EXEC(#SQL)

T sql - How to store results from a dynamic query using EXEC or EXECUTE sp_executesql

I am trying to write a dynamic query. Let's say i have a table like below, which represents the hierarchy level of a sales agent:
AgentNumber Level1Agent Level2Agent Level3Agent Level4Agent Level5Agent
1122334455 1122334499 1122334488 1122334477 1122334466 1122334455
I want to be able to dynamically select a level based on a specified agent. My EXECUTE statement seems to work correctly, but how do I get the result stored in a variable I can use later? Every answer I have found seems to only get me a success return variable, not the actual query result.
Below is my code:
DECLARE #level INT = 1;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
DECLARE #whereclause NVARCHAR(35) = CONCAT('WHERE AgentNumber = ',#agent);
DECLARE #qry NVARCHAR(300) = 'SELECT ' + #colname + ' FROM dbo.TABLE ' + #whereclause;
DECLARE #up NVARCHAR(10);
EXECUTE sp_executesql #qry, #up OUT
SELECT #up
The output of #up is NULL. If I change the last two lines to:
EXECUTE #up = sp_executesql #qry
SELECT #up
Now the output of #up is 0.
I want the output of 1122334499 and I need it stored in a variable that can later be used and inserted into a table.
Here is a fully functional example of how you can do this. Notice this is using a parameterized where clause and quotename around the column name in the dynamic sql to prevent sql injection.
if OBJECT_ID('tempdb..#Agents') is not null
drop table #Agents
create table #Agents
(
AgentNumber char(10)
, Level1Agent char(10)
, Level2Agent char(10)
, Level3Agent char(10)
, Level4Agent char(10)
, Level5Agent char(10)
)
insert #Agents
select '1122334455', '1122334499', '1122334488', '1122334477', '1122334466', '1122334455'
DECLARE #level INT = 3;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
declare #agentout char(10)
DECLARE #qry NVARCHAR(300) = 'SELECT #agent_out = ' + quotename(#colname) + ' FROM #Agents WHERE AgentNumber = #agentin';
EXECUTE sp_executesql #qry, N'#agentin char(10), #agent_out char(10) output', #agentin = #agent, #agent_out = #agentout output
select #agentout
You can try this :
DECLARE #level INT = 1;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
DECLARE #whereclause NVARCHAR(35) = CONCAT('WHERE AgentNumber = ',#agent);
DECLARE #qry NVARCHAR(300) = 'SELECT #agentout=' + #colname + ' FROM dbo.TABLE ' + #whereclause;
DECLARE #up NVARCHAR(10);
EXECUTE sp_executesql #qry, N'#agentout NVARCHAR(10) OUTPUT', #agentout=#up OUTPUT
SELECT #up
Create a variable table and makes your query insert the results you want there. Something like this:
declare #results table(field1 varchar(max), field2 varchar(max));
declare #sqlStatement varchar(max);
set #sqlStatement = 'insert into #results(field1, field2) select field1, field2 from table';
EXECUTE #sqlStatement;
select * from #results; --It will print the results from your sql statement!

Column name as a parameter in INSERT statement

I want to create one stored procedure where i want to insert values in a table.
But i don't know in which field i have to insert values and at the
runtime i will decide in which field the values should be inserted.
What i want to do is
insert into Tablename(#ColumnName, Description)
values (#ColumnValue, #MH_Description)
Can it possible that i pass this type of parameters in stored procedure as shown in the example above??
I want to use conditions too as
declare #Query nvarchar(4000)
declare #Query1 nvarchar(4000)
declare #ParmDefinition nvarchar(500);
set #Query = '
insert into tbl_temp(' + quotename(#ColumnName) +',Description)
values (#ColumnValue, #Description)'
set #Query1 = '
update tbl_temp set' + quotename(#ColumnName) +'=#ColumnValue, Description=#Description'
set #ParmDefinition = N'#ColumnValue varchar(100),#Description varchar(100)'
if exists(select 'true' from tbl_temp where quotename(#ColumnName)=#ColumnValue)
begin
exec sp_executesql #Query1, #ParmDefinition, #ColumnValue = #ColumnValue, #Description = #Description
end
else
begin exec sp_executesql #Query, #ParmDefinition, #ColumnValue= #ColumnValue, #Description = #Description
end
What am I doing wrong?
This is not possible to do with parameters. You will need to build dynamic query to achieve this.
The proc that uses dynamic SQL would look like this:
create procedure MyProc
(
#ColumnName varchar(100),
#ColumnValue varchar(100),
#MH_Description varchar(100)
)
as
begin
declare #Query nvarchar(4000)
declare #ParmDefinition nvarchar(500);
set #Query = '
insert into Tablename(' + quotename(#ColumnName) +',Description)
values (#ColumnValue, #MH_Description)'
set #ParmDefinition = N'#ColumnValue varchar(100), #MH_Description varchar(100)'
exec sp_executesql #Query, #ParmDefinition, #ColumnValue = #ColumnValue, #MH_Description = #MH_Description
end
[EDIT] Answer to your second question. Make it one query instead of two
set #Query = '
if exists(select * from tbl_temp where '+quotename(#ColumnName)+' = #ColumnValue)
update tbl_temp set' + quotename(#ColumnName) +' = #ColumnValue, Description=#Description
else
insert into tbl_temp(' + quotename(#ColumnName) +',Description)
values (#ColumnValue, #Description)'