I have been working on this all day and just cannot figure it out. So I am calling the following from CF:
<cfstoredproc procedure="SendAlert_follow-up" datasource="#Application.dsn#" debug="yes" returncode="no">
<cfprocparam type="In" cfsqltype="cf_sql_integer" variable="#accountKey" value="11" null="no">
<cfprocparam type="In" cfsqltype="cf_sql_varchar" variable="#messageBatchKey" value="D2F91D05-B972-5A1F-98B560558DCFADFB" null="no">
<cfprocparam type="In" cfsqltype="cf_sql_varchar" variable="#method" value="t" null="no">
<cfprocresult name="theResult">
</cfstoredproc>
And when I run the cfm page, I get this error:
[Macromedia][SQLServer JDBC Driver][SQLServer]Incorrect syntax near '{'.
I can run it without any problem using the MSSQL Console and it works perfectly.
Here's the beginning of the procedure:
USE [db]
GO
/****** Object: StoredProcedure [dbo].[SendAlert_follow-up] Script Date: 11/10/2022 5:59:20 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[SendAlert_follow-up]
#accountKey int,
#messageBatchKey varChar(40),
#method varChar(255)
AS
Has anyone run into this same issue? Thank you very much for any response.
Related
I have stored procedure that handles Insert and Update transactions in one of my tables for now. I'm still testing to see if there is any potential problem with this solution and how I can improve the process. This SP takes few arguments then checks for matching ID and preforms Insert or Update. I have read this Article about primary key violation error, showing that MERGE is vulnerable to concurrency problems like a multi-statement conditional INSERT/UPDATE . Seems that they have solved some issues using WITH (HOLDLOCK). I'm new in stored procedure and merge world. I would like to here your opinion if this is reliable code for application with high transactions? I might have multiple users Inserting in the same table or running Update statement at the same time. Also is there any potential issue with parameter sniffing in this case? If it is should I consider using OPTION (RECOMPILE) or that only applies to SELECT search queries? Here is example of my SQL code:
USE [TestDB]
GO
/****** Object: StoredProcedure [dbo].[SaveMaster] Script Date: 08/21/2018 10:05:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: M, D
-- Create date: 08/21/2018
-- Description: Insert/Update Master table
-- =============================================
ALTER PROCEDURE [dbo].[SaveMaster]
#RecordID INT = NULL,
#Status BIT = NULL,
#Name VARCHAR(50) = NULL,
#Code CHAR(2) = NULL,
#ActionDt DATETIME = NULL,
#ActionID UNIQUEIDENTIFIER = NULL
AS
MERGE dbo.Master WITH (HOLDLOCK) AS Target
USING (SELECT #RecordID,#Status,#Name,#Code,#ActionDt,#ActionID)
AS Source (RecordID,Status,Name,Code,ActionDt,ActionID)
ON Target.RecID = Source.RecordID
WHEN MATCHED THEN
UPDATE
SET Target.Status = Source.Status,
Target.Name = Source.Name,
Target.Code = Source.Code,
Target.ActionDt = Source.ActionDt,
Target.ActionID = Source.ActionID
WHEN NOT MATCHED THEN
INSERT(
Status,Name,Code,ActionDt,ActionID
)VALUES(
Source.Status,
Source.Name,
Source.Code,
Source.ActionDt,
Source.ActionID
);
RETURN ##ERROR;
Here is example on how I call Stored Procedure with server side language (ColdFusion 2016):
<cftransaction action="begin">
<cftry>
<cfstoredproc procedure="SaveMaster" datasource="#dsn#">
<cfprocparam dbvarname="#RecordID" value="#trim(arguments.frm_recid)#" cfsqltype="cf_sql_integer" null="#!len(trim(arguments.frm_recid))#" />
<cfprocparam dbvarname="#Status" value="#trim(arguments.frm_status)#" cfsqltype="cf_sql_bit" null="#!len(trim(arguments.frm_status))#" />
<cfprocparam dbvarname="#Name" value="#trim(arguments.frm_name)#" cfsqltype="cf_sql_varchar" maxlength="50" null="#!len(trim(arguments.frm_name))#" />
<cfprocparam dbvarname="#Code" value="#trim(frm_code)#" cfsqltype="cf_sql_char" maxlength="2" null="#!len(trim(frm_code))#" />
<cfprocparam dbvarname="#ActionDt" value="#trim(NOW())#" cfsqltype="cf_sql_datetime" />
<cfprocparam dbvarname="#ActionID" value="#trim(SESSION.UserID)#" cfsqltype="cf_sql_idstamp" null="#!len(trim(SESSION.UserID))#" />
<cfprocresult name="MasterResult"/>
</cfstoredproc>
<cfset local.fnResults = {status : "200", message : "Record successully saved!", RecID : MasterResult.RecID}>
<cfcatch type="any">
<cftransaction action="rollback" />
<cfset local.fnResults = {status : "400", message : "Error! Please contact your administrator."}>
</cfcatch>
</cftry>
</cftransaction>
As you can see I expect that Stored Procedure returns RecID that should be returned (Same ID that I pass in my stored procedure for existing records, or if does not exist then will be generated and returned like this for Insert SELECT SCOPE_IDENTITY() AS RecID; or Update like this SELECT #RecordID AS RecID). If anyone have any suggestions and know the best way to return RecID from SP that runs Insert/Update with Merge please let me know.
If anyone have any suggestions and know the best way to return RecID from SP that runs Insert/Update with Merge please let me know.
You can add an OUTPUT clause to your MERGE statement. That will allow you to return a result set containing the new ID and, if you like, what action it selected:
MERGE dbo.Master WITH (HOLDLOCK) AS Target
USING (SELECT #RecordID,#Status,#Name,#Code,#ActionDt,#ActionID)
AS Source (RecordID,Status,Name,Code,ActionDt,ActionID)
ON Target.RecID = Source.RecordID
WHEN MATCHED THEN
UPDATE
SET Target.Status = Source.Status,
Target.Name = Source.Name,
Target.Code = Source.Code,
Target.ActionDt = Source.ActionDt,
Target.ActionID = Source.ActionID
WHEN NOT MATCHED THEN
INSERT(
Status,Name,Code,ActionDt,ActionID
)VALUES(
Source.Status,
Source.Name,
Source.Code,
Source.ActionDt,
Source.ActionID
)
OUTPUT inserted.RedIC,$action as Action;
I'm assuming coldfusion will be able to consume this result set. If not, switch to the variant of OUTPUT which populates a table variable instead (OUTPUT ... INTO) and use that to set OUTPUT parameters which you add to the procedure.
I am writing migration for stored procedure with EF 6
string sqlQuery = #"
/****** Object: StoredProcedure [dbo].[GetSalesByLocation] Script Date: 9/21/2016 8:32:36 AM ******/
SET ANSI_NULLS ON GO
SET QUOTED_IDENTIFIER ON GO
CREATE PROCEDURE [dbo].[GetSalesByLocation]
#MerchantID bigint,
#LocationID bigint,
#AccountAccessID bigint,
#KioskID bigint,
#StartDate DATETIME,
#EndDate DATETIME
AS
BEGIN
.....
END
GO";
Sql(sqlQuery);
when i try to run Update-database command i get below error
Incorrect syntax near 'GO'.
Incorrect syntax near 'GO'.
'CREATE/ALTER PROCEDURE' must be the first statement in a query batch.
Incorrect syntax near 'GO'.
Also when i create SP without
SET ANSI_NULLS ON GO
SET QUOTED_IDENTIFIER ON GO
and open in SQL management studio i can see above statement getting added automatically.
So my question is if i am writing migration for stored procedure do i need to `set ansi null on explicitly?
SET ANSI_NULL and SET QUOTED_IDENTIFIER outside the procedure affects SQL Server behaviour only for the session (so it will not be written in the stored procedure and it will not affect the stored procedure behaviour when the stored procedure will be run).
Also, SET ANSI_NULL ON is the default (try SELECT GETANSINULL() on SQMS) so you could omit it. You can also omit SET QUOTED_IDENTIFIER ON (you are using [] to quote identifiers and not ").
If you need to run more statements on the same connection, in Management Studio you use GO, using ADO you can split them on different execution methods (so you will eventually see errors in the right place). Otherwise you can use ; (in this case probably you can't use ;).
I want to create StoredProcedure like this :
USE [banktest]
GO
/****** Object: StoredProcedure [dbo].[UpdatePayment] Script Date: 8/21/2015 8:22:00 AM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[UpdatePayment] #status nvarchar(50),#RefID nvarchar(50),#SaleReferenceId nvarchar(50),#paymentId int
AS
BEGIN
update bankpayment set [status]=#status,RefID=#RefID,SaleReferenceId=#SaleReferenceId where paymentid=#paymentId
END
But I have an error like this
I tried to change that name but It doesn't work .
What should i do?
Try
CREATE PROCEDURE
instead of
ALTER PROCEDURE
Follow THIS LINK for more details.
That is not an error. Just the cache is not created for that object. Please compile and I am sure you wont get any error.
Here is my stored procedure:
ALTER PROCEDURE [dbo].[Dan]
#numbers varchar(10)
AS
BEGIN
SET NOCOUNT ON;
select #numbers numbers
END
In SSMS, I can execute it successfully like this:
exec dbo.Dan '1.2'
In ColdFusion, I can execute it successfully with either of these two sets of commands:
<cfstoredproc procedure="dbo.dan" datasource="ClinicalDataDev">
<cfprocparam cfsqltype="cf_sql_varchar" value="1,2">
<cfprocresult name="abc">
</cfstoredproc>
<cfquery name="abcd" datasource="ClinicalDataDev">
exec dbo.Dan <cfqueryparam cfsqltype="cf_sql_varchar" value='1,2' list="no">
</cfquery>
However, I'm looking to improve on this by specifying the value as a list of integers. Since cfprocparam does not have a list attribute, I think I am restricted to the cfquery approach. My efforts and results so far are:
<cfqueryparam cfsqltype="cf_sql_integer" value='1' list="no">
executes successfully. The purpose is to see if the procedure accepts an
integer - it does.
<cfqueryparam cfsqltype="cf_sql_integer" value='1,2' list="no">
also executes sucessfully, but returns a value of 42006. Probably not
worth persuing.
<cfqueryparam cfsqltype="cf_sql_integer" value='1,2' list="yes">
throws an error for two many paramters.
The same thing happens with cf_sql_varchar.
As stated earlier, I can pass the list as a string, but that seems like a bit of a hack. Is there a way to pass the list of integers as a list of integers?
As other commenters mentioned before, passing table-valued parameters is the way to go. This will require you to change the input in the SP to take a table input and in your query you can do
<cfquery>
CREATE TABLE #temp (usedID int)
INSERT INTO #temp
(usedID)
VALUES
(1)
,(2)
exec dbo.Dan #temp
</cfquery>
You may have to change the way you pass your parameters to the SP, but this is the general idea.
rodmunera's answer has the correct general idea. Here is how I finally got it to work.
In sql server, I started with this:
CREATE TYPE pt.IntegerTableType AS TABLE
( integerIN int);
grant execute on type::pt.IntegerTableType to theAppropriateRole
Then I changed by stored proc to this:
ALTER PROCEDURE [dbo].[Dan]
#numbers pt.IntegerTableType readonly
AS
BEGIN
SET NOCOUNT ON;
select 1 record
where 1 in (select integerIN from #numbers)
END
The Coldfusion code is this:
<cfset numbers = "1,2">
<cfquery name="abcd" datasource="ClinicalDataDev">
declare #dan as pt.IntegerTableType
insert into #dan
select null
where 1 = 2
<cfloop list="#numbers#" index="number">
union
select <cfqueryparam cfsqltype="cf_sql_integer" value="#number#">
</cfloop>
exec dbo.Dan #dan
</cfquery>
<cfdump var="#abcd#">
This code:
USE [db]
GO
/****** Object: UserDefinedFunction [dbo].[GetFieldPickerReports] Script Date: 01/11/2013 19:12:27 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetFieldPickerReports] (#CustomerName varchar(100))
RETURNS TABLE
AS
RETURN SELECT [fpr].[ID], [fpr].[Name], [fpr].[Global], [fpr].[FPRCategoryID]
FROM FieldPickerReport fpr, dbo.GetProductKeyIdByCustomer(#CustomerName) pk
LEFT JOIN [FPRCategory] fprcat on ([fpr].[FPRCategoryID]=[fprcat].[ID])
WHERE [Global]=1 OR ProductKeyID=pk.id
Produces an error:
The multi-part identifier "fpr.FPRCategoryID" could not be bound.
This query works without the Left Join (which I currently need to add) or either with the removal of dbo.GetProductKeyIdByCustomer() and the Where clause.
Here's the code for dbo.GetProductKeyIdByCustomer()
USE [db]
GO
/****** Object: UserDefinedFunction [dbo].[GetProductKeyIdByCustomer] Script Date: 01/11/2013 19:58:34 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[GetProductKeyIdByCustomer] (#CustomerName varchar(100))
RETURNS TABLE
AS
RETURN SELECT id
FROM ProductKey
WHERE [CustomerName]=#CustomerName AND Enabled=1
What is wrong with my query?
First, I think that these UDFs would be better implemented as Views.
Second, you are mixing implicit and explicit joins. Using all explicit joins should solve your issue:
SELECT
[fpr].[ID],
[fpr].[Name],
[fpr].[Global],
[fpr].[FPRCategoryID]
FROM
FieldPickerReport fpr
JOIN dbo.GetProductKeyIdByCustomer(#CustomerName) pk
ON [Global] = 1 OR ProductKeyID = pk.id
LEFT JOIN FPRCategory fprcat
ON fpr.FPRCategoryID = fprcat.ID