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
Error: Procedure expects parameter '#params' of type 'ntext/nchar/nvarchar'.
Aim: Pass back a value based on Sql
Code: (VB.NET)
With command
.Connection = connection
.CommandText = "spAuditLoggerSystemUser" 'include audit names
.CommandType = CommandType.StoredProcedure
.Parameters.Clear()
.Parameters.AddWithValue("#EmployeeID", CInt(vEmployeeID))
Dim parameter As SqlParameter = command.Parameters.Add("#LineID", SqlDbType.Int)
parameter.Direction = ParameterDirection.Output
command.ExecuteNonQuery()
vLineID = command.Parameters("#LineID").Value.ToString()
.ExecuteNonQuery()
End With
Stored Procedure:
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[spAuditLoggerSystemUser]
(
#LineID INT OUTPUT,
#EmployeeID int
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = 'SELECT ID
FROM taylorwoodrow.dbo.TblEmployeeDetails WHERE EmployeeID = ''' + (LTRIM(RTRIM(#EmployeeID))) + '''';
EXEC sp_executesql #SQL,#LineID OUT;
PRINT #LineID
END
If do the following I return a (correct) print value:
DECLARE #SQL NVARCHAR(MAX)
DECLARE #EmployeeID AS INT
DECLARE #LineID NVARCHAR(MAX)
SET #EmployeeID = '1213'
SELECT #SQL = 'SELECT ID
FROM DB.dbo.TblEmployeeDetails WHERE EmployeeID = ''' + (LTRIM(RTRIM(#EmployeeID))) + '''';
EXEC sp_executesql #SQL,#LineID OUT;
PRINT #LineID
I used Execute stored procedure with an Output parameter? as a reference
There's no need for you to use dynamic SQL in your stored procedure. Try:
ALTER PROCEDURE [dbo].[spAuditLoggerSystemUser]
(
#LineID INT OUTPUT,
#EmployeeID int
)
AS
BEGIN
SET NOCOUNT ON;
SELECT #LineID = ID
FROM taylorwoodrow.dbo.TblEmployeeDetails
WHERE EmployeeID = #EmployeeID
END
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 :/
I am trying to make a scalar function in SQL Server. I have coined up the select statement as follows:
SET #Statement1 = 'SELECT 1 FROM ' + #p_TableName +
' WHERE RegionTypeID = 1 AND RegionID = ' +
CONVERT (nvarchar (50), #p_RegionID)
Here #p_TableName is the name of the table (nvarchar (500)) and #p_RegionID is a uniqueidentifier.
I am now executing the above statement as follows:
EXEC #ReturnValue1 = #Statement1
WHERE #ReturnValue1 is int.
But when I call this function from elsewhere I get this error:
The name 'SELECT 1 FROM [PS].[Availability] WHERE RegionTypeID = 1 AND
RegionID = AF4C182C-F751-41AD-AA6A-20A50A7A38C8' is not a valid
identifier.
I need to know how I can call a dynamic sql select statement from within a scalar function.
You can create SP like below with output parameter:
CREATE PROCEDURE ProcNameGoesHere
#p_TableName nvarchar(500),
#p_RegionID uniqueidentifier,
#output int OUTPUT
AS
BEGIN
DECLARE #Statement1 nvarchar(max),
#ParmDefinition nvarchar(500)
SET #Statement1 = N'SELECT #someValue = 1 FROM ' + #p_TableName +
' WHERE RegionTypeID = 1 AND RegionID = ' +
CONVERT (nvarchar (50), #p_RegionID)
SET #ParmDefinition = N'#someValue int OUTPUT'
EXEC sp_executesql #Statement1, #ParmDefinition, #output=#someValue OUTPUT
RETURN;
END
Then you can call it like this:
DECLARE #output int
EXEC ProcNameGoesHere '[PS].[Availability]','AF4C182C-F751-41AD-AA6A-20A50A7A38C8', #output OUTPUT
SELECT #output
Or:
IF ISNULL(#output,0) = 1
BEGIN
--Do something here
END
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