Stored procedure expects parameter 'Incorrect syntax near ':'.' - sql

I have the following stored procedure in SQL Server:
CREATE PROCEDURE [PROC_SET_BRN_RPT_STSTC]
#I_RPT_I varchar(max),
#I_MSTR_TBL varchar(max)
AS
BEGIN
DECLARE
#VD_PSTG_D datetime2(0),
#V_SQL varchar(4000),
#BMG_RPT_I varchar(5) = ISNULL(#I_RPT_I, '') + 'M',
#MAM_RPT_I varchar(5) = ISNULL(#I_RPT_I, '') + 'P';
/*vd_pstg_d := GET_DATE ('TDTD');*/
SELECT #VD_PSTG_D = max(TIME_DIMN.DATE_D)
FROM TIME_DIMN
WHERE TIME_DIMN.TME_DIMN_I IN ( 'TDTD', 'TDSH' );
DECLARE #SQLString NVARCHAR(500);
SET #SQLString = 'Delete From RPT_STSTC Where TXN_PSTG_D = :1 and Rpt_i = :2';
Execute sp_executesql #SQLString, #vd_pstg_d, #I_Rpt_I;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
When I try to execute the stored procedure, I get the following error:
Incorrect syntax near ':'.
Do you know what would be the issue?

As pointed out in the comment on your question, there is no need for dynamic SQL in this stored procedure. You could just rewrite it:
CREATE PROCEDURE [PROC_SET_BRN_RPT_STSTC]
#I_RPT_I varchar(max),
#I_MSTR_TBL varchar(max)
AS
BEGIN
DECLARE
#VD_PSTG_D datetime2(0),
#V_SQL varchar(4000),
#BMG_RPT_I varchar(5) = ISNULL(#I_RPT_I, '') + 'M',
#MAM_RPT_I varchar(5) = ISNULL(#I_RPT_I, '') + 'P';
/*vd_pstg_d := GET_DATE ('TDTD');*/
SELECT #VD_PSTG_D = max(TIME_DIMN.DATE_D)
FROM TIME_DIMN
WHERE TIME_DIMN.TME_DIMN_I IN ( 'TDTD', 'TDSH' );
DELETE FROM RPT_STSTC
WHERE TXN_PSTG_D = #vd_pstg_d AND Rpt_i = #I_Rpt_I;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;
Only use sp_executesql if you absolutely need to use it - here you do not need it.
Just to answer your question, here is what you could have done (but it is not advised in this simple scenario):
CREATE PROCEDURE [PROC_SET_BRN_RPT_STSTC]
#I_RPT_I varchar(max),
#I_MSTR_TBL varchar(max)
AS
BEGIN
DECLARE
#VD_PSTG_D datetime2(0),
#V_SQL varchar(4000),
#BMG_RPT_I varchar(5) = ISNULL(#I_RPT_I, '') + 'M',
#MAM_RPT_I varchar(5) = ISNULL(#I_RPT_I, '') + 'P';
/*vd_pstg_d := GET_DATE ('TDTD');*/
SELECT #VD_PSTG_D = max(TIME_DIMN.DATE_D)
FROM TIME_DIMN
WHERE TIME_DIMN.TME_DIMN_I IN ( 'TDTD', 'TDSH' );
DECLARE #SQLString NVARCHAR(500);
SET #SQLString = CONCAT('Delete From RPT_STSTC Where TXN_PSTG_D =''', #VD_PSTG_D, ''' AND Rpt_i=''', #I_RPT_I, '''');
Execute sp_executesql #SQLString, #vd_pstg_d, #I_Rpt_I;
IF ##TRANCOUNT > 0
COMMIT TRANSACTION;

The :1 and :2 are the problem.
You want to fill variables in there, but that is the wrong way. You need to use the variables there and cant use placeholes like in other languages.
SET #SQLString = 'Delete From RPT_STSTC Where TXN_PSTG_D = #vd_pstg_d and Rpt_i = #I_Rpt_I';
The syntax with :1 and :2 does not exist in T-SQL.

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;

SQL Trigger - Commit Update and CATCH Block of Procedure

I have a trigger on a table that executes a stored procedure. The executed stored procedure has a TRY/CATCH, so that if there is an error, a row is inserted into a log table.
When the stored procedure fails, I'm getting the following error:
The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.
How do I make it so the update get committed and the CATCH in the stored procedure is also executed? If I add:
IF ##TRANCOUNT > 0
ROLLBACK TRAN
to the stored procedure, then I get the following error:
The transaction ended in the trigger. The batch has been aborted.
Trigger:
ALTER TRIGGER [dbo].[trigger123] ON [dbo].[tbl321]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE (status)
BEGIN
IF EXISTS (--some condition)
BEGIN
EXEC SProc
END
END
END
SProc:
ALTER PROCEDURE [dbo].[SProc ]
AS
BEGIN
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
BEGIN TRY
select #sql = '
declare #error1 varchar(255),
#error2 varchar(255),
#error3 varchar(255)
Exec SomeDB.DBO.ConfirmStatus ''A10594'',#error1 output,#error2 output,#error3 output
if ISNULL(#error1,0) <> 0
begin
set #error1 = ISNULL(#error2,'''') + '' '' + ISNULL(#error3,'''') + '' '' + ISNULL(#error1,0)
RAISERROR (#error1, 16, 1)
end'
from jobs j
exec(#sql) at [linked_server]
update status
set status_prev = 1
END TRY
BEGIN CATCH
SELECT
#ErrorMessage = ERROR_MESSAGE(),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE()
INSERT INTO error_log (error_datetime, [error_message])
SELECT
GETDATE(),
'Msg: ' + ISNULL(CONVERT(VARCHAR, ERROR_NUMBER()), 'N/A') + ', Level: ' + ISNULL(CONVERT(VARCHAR, #ErrorSeverity), 'N/A') + ', Line: ' + ISNULL(CONVERT(VARCHAR, ERROR_LINE()), 'N/A') + ', Error: ' + ISNULL(#ErrorMessage, 'N/A')
END CATCH
END
I was able to modify my stored procedure to not use a try/catch. This gets me what I need.
ALTER PROCEDURE [dbo].[SProc ]
AS
BEGIN
DECLARE #error table (error1 varchar(255))
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
BEGIN TRY
select #sql = '
declare #error1 varchar(255),
#error2 varchar(255),
#error3 varchar(255)
Exec SomeDB.DBO.ConfirmStatus ''A10594'',#error1 output,#error2 output,#error3 output
if ISNULL(#error1,0) <> 0
begin
set #error1 = ISNULL(#error2,'''') + '' '' + ISNULL(#error3,'''') + '' '' + ISNULL(#error1,0)
select #error1
end'
from jobs j
insert into #error
exec(#sql) at [linked_server]
if exists (select top 1 error1 from #error)
begin
INSERT INTO error_log (error_datetime, [error_message])
SELECT
GETDATE(),
(select top 1 error1 from #error)
else
update status
set status_prev = 1
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

Error coming while creating UDF in Sql Server 2005

Does anyone know what's wrong with this code block.
CREATE FUNCTION [dbo].[udfGetPoint]
(
#UserID INT,
#SqlCountry VARCHAR(1000)
)
RETURNS INT
AS
BEGIN
DECLARE #Points INT
SET #Points = 1
DECLARE #RecordCount sysname
IF #SqlCountry <> ''
BEGIN
EXEC sp_executesql
N'SELECT #DynamicCount = COUNT(UserID) FROM Country WHERE UserID = '+#UserID+' AND LCValues IN (' + #SqlCountry + ')'
,N'#DynamicCount sysname OUTPUT'
,#RecordCount OUTPUT
IF #RecordCount > 0
SET #Points = #Points + 1
END
RETURN #Points
END
If i execute this i got following error:
Msg 102, Level 15, State 1, Procedure udfGetPoint, Line 15
Incorrect syntax near '+'.
You can't concatenate in the parameter setting of a stored procedure.
DECLARE #sql varchar(2000)
SET #SQL = 'SELECT #DynamicCount = COUNT(UserID) FROM Country WHERE UserID = '+#UserID+' AND LCValues IN (' + #SqlCountry + ')'
EXEC sp_executesql
#SQL
,N'#DynamicCount sysname OUTPUT'
,#RecordCount OUTPUT

sql server procedure error

CREATE PROCEDURE USP_SEARCH_HOTELS
(
#Text varchar(50),
#Type varchar(40)
)
AS
BEGIN
Declare #Query VARCHAR(60)
IF #Type = 'By Country'
BEGIN
SET #Query = 'Hotel.countryName like '+ #Text+'%'
END
ELSE IF #Type = 'By State'
BEGIN
SET #Query = 'HOTEL.stateName like '+ #Text+'%'
END
ELSE IF #Type='By Property Name'
BEGIN
SET #Query='hotel.propertyname like'+ #Text+'%'
End
ELSE IF #Type='By Rating'
BEGIN
SET #Query='hotel.starRating='+ Cast(#Text as INT)
END
ELSE IF #Type='By City'
BEGIN
SET #Query='hotel.cityName like '+ #Text+'%'
END
begin
select * from hotel,tbl_cust_info
where
hotel.agentID=Tbl_Cust_Info.Cust_ID
and
(#Query)
end
END
WHAT IS THE ERROR IN THIS PROCEDURE PLEASE HELP.
DECLARE #Final nvarchar(1000) -- Separate partial and final
DECLARE #Partial nvarchar(100) -- let's you maintain and debug better
SET #Final = 'select * from hotel
join tbl_cust_info
on hotel.agentID=Tbl_Cust_Info.Cust_ID
where' + #Partial
Assumiung that you are invioking this via .NET run a Regexp on the Text to eliminate all chars that are not letters or space. Like [!##$%^&*()?;:'"\|].
Consider rewriting as 5 sprocs (HotelsByCountry, HotelsByState, HotelsByCity, HotelsByName, HotelsByRating). That will increase you perf and let you do orderby and paging (like Row_number() OVER(order by StartDate)). It will also make them totally safe.