SQL Server stored procedure passing old values not new value - sql-server

This is my table:
search_id search_term clicked count
------------------------------
1 rabbit 0 5
2 airline 1 4
And this is my stored procedure:
alter procedure update_item
(#search_id int,
#search_term varchar(50),
#clicked int)
as
begin
update search_events
set search_term= #search_term,
clicked = #clicked
where search_id = #search_id
end
--exec update_item #search_id=1,#search_term='rabbit',#clicked=0
I created a stored procedure and I pass two parameters.
I want to pass only one of parameter to update the record and second parameter value will be old value.
It is possible that passing the parameter with the old value.
For example:
exec update_item #search_id= 1, #search_term= 'pass here old value that it is rabbit', #clicked = 1
Update only clicked value that it is 1 from 0.

If you only need a single parameter, you can use a simple if statement, and omit the set clause if the value is null
CREATE PROCEDURE update_item (
#search_id INT
,#search_term VARCHAR(50)
,#clicked INT
)
AS
BEGIN
IF (#search_term IS NULL)
UPDATE search_events
SET clicked = #clicked
WHERE search_id = #search_id
ELSE
UPDATE search_events
SET search_term = #search_term
,clicked = #clicked
WHERE search_id = #search_id
END
If you have more parameters that you need to check, then you'd need to build the update statement dynamically. A basic example as follows:
ALTER PROCEDURE update_item (
#search_id INT
,#search_term VARCHAR(50)
,#clicked INT
)
AS
BEGIN
DECLARE #Sql NVARCHAR(4000) = N'UPDATE search_events SET ',
#Params NVARCHAR(300) = N'#search_id INT, #search_term VARCHAR(50), #clicked INT'
IF (#search_term IS NOT NULL)
SET #Sql = #Sql + ' search_term = #search_term,'
SET #Sql = #Sql + ' clicked = #clicked'
SET #Sql = #Sql + ' WHERE search_id = #search_id'
EXEC sp_executesql #Sql, #Params, #search_id=#search_id, #search_term=#search_term, #clicked=#clicked
END

Related

Table Name from parameter in Stored Procedure

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

Procedure expects parameter '#params' of type 'ntext/nchar/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

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 :/

Executing dynamic query inside a scalar function sql server

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

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