Table Name from parameter in Stored Procedure - sql-server

I'm trying to create a stored procedure. Here's a short version of my code:
CREATE PROCEDURE foobar
#table_name nvarchar(20),
#Work_Status nvarchar(20)
AS
BEGIN
update #table_name -- /// How Do I do this? ///
set work_status = #Work_Status
END
How can I define the table name via a parameter?

Try to use a dynamic query:
DECLARE #SQL NVARCHAR(4000)
DECLARE #ParamDefinition nvarchar(500)
SET #ParamDefinition = N'#Work_Status nvarchar(20), #day_no nvarchar(10), #day_month nvarchar(10), #day_years nvarchar(10)';
--...CURSOR declaration
--... BEGIN
SELECT #SQL =
N'update [SKTH_ENSUSER].[dbo].' + #tbl_name + '
set t_work_status = #Work_Status
where t_day_no = #day_no and t_month_no = #day_month and t_year_no = #day_years'
EXECUTE sp_executesql #SQL, #ParamDefinition, #Work_Status = #Work_Status, #day_no = #day_no, #day_month = #day_month, #day_years = #day_years
--...
-- FETCH NEXT FROM ENS_cursor
Updated: #SQL must be NVARCHAR

Related

Assign result of dynamic SQL in Procedure A to variable defined in Procedure B

I am struggling with getting the result back for a dynamic query that is being called from a different stored procedures. Here is what I am trying to achieve.
Procedure A:
CREATE PROCEDURE A
#C1 int, #F1 int
AS
SET #SQL = 'SELECT ID FROM EMPLOYEE_TABLE WHERE '+#C1+' = +'#F1'
EXEC(#SQL)
Procedure B:
CREATE PROCEDURE B
#C1 int, #F1 int
AS
DECLARE #Result INT
EXEC #Result = A #C1, #F1
I need to run stored procedure B and let it return back to me the result. I just cannot seem to get the correct result back. How can I fix this problem?
You can try the following two store procedures query statement
Procedure A:
ALTER PROCEDURE A
#C1 VARCHAR(250),
#F1 int
AS
DECLARE #SQL AS VARCHAR(MAX);
SET #SQL = 'SELECT ID FROM PatientTest WHERE '+ #C1+' = ' + CONVERT(VARCHAR(12),#F1)
EXEC(#SQL)
Procedure B:
ALTER PROCEDURE B
#C1 VARCHAR(250),
#F1 int
AS
Declare #Result int
EXEC #Result = A #C1, #F1
If you will face further problem, please let me know in comment. Thanks.
Try these two. I think you will meet your expected result.
Procedure 1
CREATE PROCEDURE GetValue
#ColumnName VARCHAR(250),
#ColumnValue VARCHAR(250)
AS
DECLARE #SQL AS VARCHAR(MAX);
SET #SQL = 'SELECT Email FROM Person WHERE '+ #ColumnName + ' = ''' + #ColumnValue + ''''
EXEC (#SQL)
-- EXEC GetValue 'MobileNo', '+8801919111333'
Procedure 2
CREATE PROCEDURE ReturnValue
#ColumnName VARCHAR(250),
#ColumnValue VARCHAR(250)
AS
DECLARE #Result VARCHAR(250)
EXEC #Result = GetValue #ColumnName, #ColumnValue
-- EXEC ReturnValue 'MobileNo', '+8801919111333'

Stored procedure not returning results from table variable?

I have a stored procedure that I'm working on and I'm trying to get it to return the results that are stored into a table variable that I created within the procedure. For some reason, its not returning anything when I execute the procedure. However, if I take the piece of code used to populate the table variable and take it out of the procedure it works...
The code is as follows:
Test Code
DECLARE #RC int
DECLARE #constraint_names nvarchar(max)
DECLARE #column_names nvarchar(max)
DECLARE #table_name nvarchar(max)
DECLARE #table_schema nvarchar(max)
DECLARE #database_name nvarchar(max)
DECLARE #debug int
DECLARE #ExistFlag int;
-- TODO: Set parameter values here.
SET #column_names = 'M2016_Object_ID int, Name varchar(50), a int, b'
SET #table_name = 'tblM2016_Objects';
SET #debug = 0;
SET #ExistFlag = 1;
DECLARE #existing_cols TABLE (Value nvarchar(max));
INSERT INTO #existing_cols EXEC spM2016_CheckColumnExistence_tblM2016
#column_names, #table_name, #database_name, #table_schema, 1, 0;
select * from #existing_cols
Results
Value
M2016_Object_ID int
Name varchar(50)
This is the expected result since I'm testing to see if M2016_Object_ID and Name column exist in the tblM2016_Objects table.
However, when I execute this inside the stored procedure I'm working on, it returns nothing.
Stored Procedure
ALTER PROCEDURE spM2016_ChangePKConstraints_tblM2016
-- Add the parameters for the stored procedure here
#constraint_names nvarchar(max) =
N'PK_tblM2016_Fields_M2016_Field_ID',
#column_names nvarchar(max) = N'M2016_Field_ID',
#table_name nvarchar(max) = N'tblM2016_Fields',
#table_schema nvarchar(max) = N'dbo',
#database_name nvarchar(max) = N'MET',
#debug int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #tbl_name nvarchar(max) = N'tblM2016_Fields',
#col_names nvarchar(max) = N'M2016_Field_ID',
#tbl_schema nvarchar(max) = N'dbo',
#db_name nvarchar(max) = N'MET',
#tbl_full_name nvarchar(max),
#tbl_short_name nvarchar(max),
#sql nvarchar(max),
#params nvarchar(max)
-- Insert statements for procedure here
SET #col_names = ISNULL(NULLIF(#column_names, ''), #col_names);
SET #tbl_name = quotename(ISNULL(NULLIF(#table_name, ''), #tbl_name));
SET #tbl_schema = quotename(ISNULL(NULLIF(#table_schema, ''), #tbl_schema));
SET #db_name = quotename(ISNULL(NULLIF(#database_name, ''), #db_name));
SET #tbl_full_name = #db_name + '.' + #tbl_schema + '.' + #tbl_name;
SET #tbl_short_name = #tbl_schema + '.' + #tbl_name;
DECLARE #existing_cols TABLE (Value nvarchar(max));
DECLARE #nonexisting_cols TABLE (Value nvarchar(max));
--INSERT INTO #split_columns
-- SELECT *
-- FROM
-- fnM2016_Split_String_Inline(#col_names, ',');
--IF (#debug = 1)
-- SELECT * FROM #split_columns;
IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'PK' AND parent_object_id = OBJECT_ID(#tbl_full_name))
BEGIN
-- No PK constraint, check col_names to see which exist and don't exist
INSERT INTO #existing_cols EXEC spM2016_CheckColumnExistence_tblM2016 #col_names, #tbl_name, #db_name, #tbl_schema, 1, 0;
INSERT INTO #nonexisting_cols EXEC spM2016_CheckColumnExistence_tblM2016 #col_names, #tbl_name, #db_name, #tbl_schema, 0, 0;
SELECT * FROM #existing_cols;
SELECT * FROM #nonexisting_cols;
END
--ELSE
--BEGIN
--END
END
Results
These are the results after executing the procedure with the same parameter values in the test above:
EXECUTE #RC = [dbo].[spM2016_ChangePKConstraints_tblM2016]
#constraint_names
,#column_names
,#table_name
,#table_schema
,#database_name
,#debug;
Result
Value
The table purposely does not have a primary key. Proof:
In your procedure, change the name of the table in your Declare section.
This should fix the issue.
ALTER PROCEDURE spM2016_ChangePKConstraints_tblM2016
-- Add the parameters for the stored procedure here
#constraint_names nvarchar(max) =
N'PK_tblM2016_Fields_M2016_Field_ID',
#column_names nvarchar(max) = N'M2016_Field_ID',
#table_name nvarchar(max) = N'tblM2016_Objects',
#table_schema nvarchar(max) = N'dbo',
#database_name nvarchar(max) = N'MET',
#debug int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #tbl_name nvarchar(max) = N'tblM2016_Objects',
#col_names nvarchar(max) = N'M2016_Field_ID',
#tbl_schema nvarchar(max) = N'dbo',
#db_name nvarchar(max) = N'MET',
#tbl_full_name nvarchar(max),
#tbl_short_name nvarchar(max),
#sql nvarchar(max),
#params nvarchar(max)
I figured out the issue. My #table_name, #table_schema, and #database_name being passed into the spM2016_CheckColumnExistence_tblM2016 procedure inside the spM2016_ChangePKConstraints_tblM2016 were already escaped through the call to quotename(). Inside the spM2016_CheckColumnExistence_tblM2016, I also do a qutoename() of the parameters as a validation check against bad table, database, and schema names. That procedure code was left out and I apologize for that.
Essentially the problem area is here (with problem parameters highlighted with **)
Problem code in spM2016_ChangePKConstraints_tblM2016
INSERT INTO #existing_cols EXEC spM2016_CheckColumnExistence_tblM2016 #col_names, **#tbl_name**, **#db_name**, **#tbl_schema**, 1, 0;
Notice that those parameters being passed to spM2016_CheckColumnExistence_tblM2016 have already been escaped with quotename() above in the spM2016_ChangePKConstraints_tblM2016 procedure. Now, here is the missing key code in the spM2016_CheckColumnExistence_tblM2016 procedure:
Problem code in spM2016_CheckColumnExistence_tblM2016
ALTER PROCEDURE spM2016_CheckColumnExistence_tblM2016
-- Add the parameters for the stored procedure here
#column_names nvarchar(max) = N'M2016_Field_ID int',
#table_name nvarchar(max) = N'tblM2016_Fields',
#database_name nvarchar(max) = N'MET',
#table_schema nvarchar(max) = N'dbo',
#ExistFlag int = 1, -- Check for column existence in given table = 1
-- Check for column non-existence in given table = 0
#debug int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #tbl_name nvarchar(max) = N'tblM2016_Fields',
#col_names nvarchar(max) = N'M2016_Field_ID',
#tbl_schema nvarchar(max) = N'dbo',
#db_name nvarchar(max) = N'MET',
#tbl_full_name nvarchar(max),
#tbl_short_name nvarchar(max)
-- Insert statements for procedure here
***** PROBLEM STARTS HERE *****
SET #col_names = ISNULL(NULLIF(#column_names, ''), #col_names);
SET #tbl_name = quotename(ISNULL(NULLIF(#table_name, ''), #tbl_name));
SET #tbl_schema = quotename(ISNULL(NULLIF(#table_schema, ''), #tbl_schema));
SET #db_name = quotename(ISNULL(NULLIF(#database_name, ''), #db_name));
SET #tbl_full_name = #db_name + '.' + #tbl_schema + '.' + #tbl_name;
SET #tbl_short_name = #tbl_schema + '.' + #tbl_name;
I've highlighted the issue with ***** PROBLEM STARTS HERE ***** for clarity. As you can see, spM2016_CheckColumnExistence_tblM2016 also does a quotename call to make sure the #table_name, #table_schema, and #database_name passed to spM2016_CheckColumnExistence_tblM2016 has proper escaping as well. But, since I passed the already quotenamed #table_name, #table_schema, and #database_name from spM2016_ChangePKConstraints_tblM2016 into spM2016_CheckColumnExistence_tblM2016 as #col_names, #tbl_name, #db_name, #tbl_schema, they got double quoted and were thus unrecognizable when doing comparisons in the sys.object queries in spM2016_CheckColumnExistence_tblM2016 and so were returning bogus results.
The reason the test code worked is because the parameters were not already escaped when passed into the spM2016_CheckColumnExistence_tblM2016, thus causing the table variable to execute fine.
Turns out, it had nothing to do with the table variable :/

Must Declare Scalar variable #nRuleId

USE GDMDBNS_1720
GO
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_TYPE = 'PROCEDURE'
AND ROUTINE_SCHEMA = 'dbo' AND ROUTINE_NAME = 'usp_RmsExecuteValidationRule')
BEGIN
DROP PROCEDURE dbo.usp_RmsExecuteValidationRule
END
GO
Create PROCEDURE [dbo].[usp_RmsExecuteValidationRule]
#nRuleId INT,
#FIPSName VARCHAR(5)
AS
BEGIN
DECLARE #strRuleQuery VARCHAR(MAX)
DECLARE #sqlstat AS NVARCHAR(MAX)
DECLARE #params AS NVARCHAR(MAX)
SET #strRuleQuery = N'SELECT RULE_QUERY from GdmValidationRuleMaster where
RULE_ID = #nRuleId'
SET #sqlstat = #strRuleQuery
SET #params = N'#FIPSName VARCHAR(5)'
EXEC sp_executesql #params,
#query = #sqlstat,
#FIPSName = #FIPSName
END
got error while Debugging must declare scalar variable #nRuleId . I have already declared. But error is pooping out always.
There appear to be a number of issues with the code, as is.
To return a value, you need to declare an OUTPUT parameter and the variable #FIPSName is not actually used in the code, and #strRuleQuery is superfluous in this code.
Here is the code from inside the SProc, that should be closer to your needs.
-- Parameters
DECLARE
#nRuleId INT = 1,
#FIPSName VARCHAR(5) = 'ITS'
-- Local variables
DECLARE #sqlstat AS NVARCHAR(MAX)
DECLARE #params AS NVARCHAR(MAX)
DECLARE #RULE_QUERY NVARCHAR(MAX)
SET #sqlstat = N'SELECT #RULE_QUERY=RULE_QUERY from GdmValidationRuleMaster where RULE_ID = #nRuleId'
SET #params = N'#nRuleId INT, #RULE_QUERY NVARCHAR(MAX) OUTPUT'
EXEC sp_executesql
#sqlstat,
#params,
#nRuleId = #nRuleId, #RULE_QUERY= #RULE_QUERY OUTPUT
-- Output
SELECT #RULE_QUERY
You must rewrite execution part:
SET #params = N'#FIPSName VARCHAR(5), #nRuleId int'
EXEC sp_executesql #strRuleQuery, #params, #FIPSName = #FIPSName, #nRuleId = #nRuleId
I don't understand, why do you pass #FIPSName as parameter, it is not used in your batch.

SQL server 2012 - return variable value from a dynamic script

I'm trying to run a dynamic script to then return the variable so I can pass in to the rest of my script. I've a couple of ways with the help of Google, but I think I still haven't got the syntax correct, therefore getting error or null value returned.
Can someone please advise where I've gone wrong.
For example:
To return the value for variable #table_name
ASIA is the database and this is set as variable which is appended to the table name that is retrieved from the table and T5148 is the id from the table to turn the table name as is so a variable. I have set this a variables as this script sits when other scripts which loops
Thank you
declare #table_name nvarchar(50)
declare #database nvarchar(50)
declare #id nvarchar(50)
declare #sql nvarchar(max)
set #database = 'ASIA'
set #id = 'T5178'
set #sql = N'SELECT #table_name = ''#database''+table_name
FROM ''#database''+tables (NOLOCK)
WHERE id = ''#id'''
exec sp_executesql #sql, N'#table_name nvarchar(50) output', #table_name output
select #TRAN_TABLE
If I am not wrong, this is what you need :
DECLARE #table_name NVARCHAR(50)
DECLARE #database NVARCHAR(50)
DECLARE #id NVARCHAR(50)
DECLARE #sql NVARCHAR(MAX)
SET #database = 'ASIA'
SET #id = 'T5178'
SET #sql = N'SELECT #table_name = table_name
FROM ' + #database+'.dbo.tables (NOLOCK)
WHERE id = #id'
EXEC SP_EXECUTESQL #sql, N'#id nvarchar(50),#table_name nvarchar(50) output',
#id = #id, #table_name = #table_name OUTPUT
SET #table_name = #database + #table_name
Note : change dbo as you schema name.

Can I specify a database name dynamically in a trigger?

I need to get data from a table in a database who's database name will be determined as a variable during a trigger. I then, knowing this variable need to get a seqno from a table in the determined database for a item which was also determined as a variable during a trigger.
I am trying this route as I assume I need to build the SQL statement before I set it to a variable.
This is not working and I need to know the best way on how I can do this:
DECLARE #SU_SEQNO INTEGER, #SU_NAME VARCHAR(50), #SU_OWNER VARCHAR(15), #SUD_SEQNO INTEGER, #SQL NVARCHAR(500)
SET #SU_OWNER = 'XXX'
SET #SU_NAME = '1ABC234'
SET #SQL ='SELECT #SUD_SEQNO=SEQNO FROM ' + (#SU_OWNER) + '.SU_MAIN
WHERE UNITNAME= ' + #SU_NAME
SET #SUD_SEQNO = (EXECUTE (#SQL))
Thanks alot for any help with this
From: Get result from dynamic SQL in stored procedure
SET #SQL = N'SELECT DISTINCT #FiscalYear = FiscalYear FROM ' + #DataSource;
EXEC sp_executesql #SQL, N'#FiscalYear INT OUTPUT', #FiscalYear OUTPUT;
PRINT #FiscalYear;
I'd re-engineer to use the sp_executesql method as shown above. That should do the trick.
I have amended the code, and it works
declare #su_owner varchar(15) = 'DBTEST'
declare #SU_SEQNO INTEGER=1, #SUD_SEQNO INTEGER=0, #SQL NVARCHAR(500)
DECLARE #ParmDefinition NVARCHAR(500), #SU_NAME_INPUT VARCHAR(50)='SU123'
SET #SU_NAME_INPUT = (SELECT UNITNAME FROM SU_MAIN WHERE SEQNO=#SU_SEQNO)
SET #SU_NAME = (SELECT UNITNAME FROM SU_MAIN WHERE SEQNO=#SU_SEQNO)
SET #SQL = N'SELECT #sud_seqnoOUT=MAX(SEQNO) FROM ' + quotename(#su_owner) + '.[dbo].[SU_MAIN] WHERE UNITNAME]=#SU_NAME_INPUT' ;
SET #ParmDefinition = N'#SU_NAME_INPUT VARCHAR(50),#sud_seqnoOUT INT OUTPUT'
EXEC sp_executesql #SQL,#ParmDefinition,#SU_NAME_INPUT = #SU_NAME,
#sud_seqnoOUT = #SUD_SEQNO OUTPUT

Resources