Related
G'day. I'm trying to create a basic function which checks for the number of records matching a certain criteria. If there are none then it performs an insert and returns returns 0, otherwise it updates the existing record and returns 1. I'm getting a syntax error at the location of the Insert and Update statements. Here is my SQL script (FYI I'm new to pervasive and if anyone has a better way to perform an update/insert then I'm all ears/eyes):
CREATE FUNCTION "InsertUpdateWebData"(:KeyType CHAR(1), :KeyValue CHAR(50),
:WebData CHAR(100), :WhiteSpace LONGVARCHAR, :Spare CHAR(97)) RETURNS INTEGER
AS
BEGIN
DECLARE :RecordCount INTEGER;
SET :RecordCount = (SELECT COUNT(*) FROM SYS_WebData WHERE WBD_KeyType
= :KeyType and WBD_KeyValue = :KeyValue);
IF :RecordCount = 0 THEN
BEGIN
INSERT INTO SYS_WebData(WBD_KeyType, WBD_KeyValue, WBD_Data,
WBD_WhiteSpace, WBD_Spare) VALUES (:KeyType, :KeyValue, :WebData,
:WhiteSpace, :Spare);
RETURN 0;
END
ELSE
BEGIN
UPDATE SYS_WebData SET WBD_Data = :WebData, WBD_WhiteSpace = :WhiteSpace,
WBD_Spare = :Spare WHERE WBD_KeyType = :KeyType AND WBD_KeyValue =
:KeyValue;
RETURN 1;
END
END IF
END
What would be the correct syntax to do this?
From the Pervasive documentation:
Restrictions
You cannot use the CREATE DATABASE or the DROP DATABASE statement in a
user-defined function. The table actions CREATE, ALTER, UPDATE,
DELETE, and INSERT are not permitted within a user-defined function.
You should be able to change it from CREATE FUNCTION to CREATE PROCEDURE and have it work. I did that and it created the procedure.
I am developing my very first stored procedure in SQL Server 2008 and need advice concerning the errors message.
Procedure or function xxx too many arguments specified
which I get after executing the stored procedure [dbo].[M_UPDATES] that calls another stored procedure called etl_M_Update_Promo.
When calling [dbo].[M_UPDATES] (code see below) via right-mouse-click and ‘Execute stored procedure’ the query that appears in the query-window is:
USE [Database_Test]
GO
DECLARE #return_value int
EXEC #return_value = [dbo].[M_UPDATES]
SELECT 'Return Value' = #return_value
GO
The output is
Msg 8144, Level 16, State 2, Procedure etl_M_Update_Promo, Line 0
Procedure or function etl_M_Update_Promo has too many arguments specified.
QUESTION: What does this error message exactly mean, i.e. where are too many arguments? How to identify them?
I found several threads asking about this error message, but the codes provided were all different to mine (if not in another language like C# anyway). So none of the answers solved the problem of my SQL query (i.e. SPs).
Note: below I provide the code used for the two SPs, but I changed the database names, table names and column names. So, please, don’t be concerned about naming conventions, these are only example names!
(1) Code for SP1 [dbo].[M_UPDATES]
USE [Database_Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ M_UPDATES] AS
declare #GenID bigint
declare #Description nvarchar(50)
Set #GenID = SCOPE_IDENTITY()
Set #Description = 'M Update'
BEGIN
EXEC etl.etl_M_Update_Promo #GenID, #Description
END
GO
(2) Code for SP2 [etl_M_Update_Promo]
USE [Database_Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0
as
declare #start datetime = getdate ()
declare #Process varchar (100) = 'Update_Promo'
declare #SummeryOfTable TABLE (Change varchar (20))
declare #Description nvarchar(50)
declare #ErrorNo int
, #ErrorMsg varchar (max)
declare #Inserts int = 0
, #Updates int = 0
, #Deleted int = 0
, #OwnGenId bit = 0
begin try
if #GenId = 0 begin
INSERT INTO Logging.dbo.ETL_Gen (Starttime)
VALUES (#start)
SET #GenId = SCOPE_IDENTITY()
SET #OwnGenId = 1
end
MERGE [Database_Test].[dbo].[Promo] AS TARGET
USING OPENQUERY( M ,'select * from m.PROMO' ) AS SOURCE
ON (TARGET.[E] = SOURCE.[E])
WHEN MATCHED AND TARGET.[A] <> SOURCE.[A]
OR TARGET.[B] <> SOURCE.[B]
OR TARGET.[C] <> SOURCE.[C]
THEN
UPDATE SET TARGET.[A] = SOURCE.[A]
,TARGET.[B] = SOURCE.[B]
, TARGET.[C] = SOURCE.[c]
WHEN NOT MATCHED BY TARGET THEN
INSERT ([E]
,[A]
,[B]
,[C]
,[D]
,[F]
,[G]
,[H]
,[I]
,[J]
,[K]
,[L]
)
VALUES (SOURCE.[E]
,SOURCE.[A]
,SOURCE.[B]
,SOURCE.[C]
,SOURCE.[D]
,SOURCE.[F]
,SOURCE.[G]
,SOURCE.[H]
,SOURCE.[I]
,SOURCE.[J]
,SOURCE.[K]
,SOURCE.[L]
)
OUTPUT $ACTION INTO #SummeryOfTable;
with cte as (
SELECT
Change,
COUNT(*) AS CountPerChange
FROM #SummeryOfTable
GROUP BY Change
)
SELECT
#Inserts =
CASE Change
WHEN 'INSERT' THEN CountPerChange ELSE #Inserts
END,
#Updates =
CASE Change
WHEN 'UPDATE' THEN CountPerChange ELSE #Updates
END,
#Deleted =
CASE Change
WHEN 'DELETE' THEN CountPerChange ELSE #Deleted
END
FROM cte
INSERT INTO Logging.dbo.ETL_log (GenID, Startdate, Enddate, Process, Message, Inserts, Updates, Deleted,Description)
VALUES (#GenId, #start, GETDATE(), #Process, 'ETL succeded', #Inserts, #Updates, #Deleted,#Description)
if #OwnGenId = 1
UPDATE Logging.dbo.ETL_Gen
SET Endtime = GETDATE()
WHERE ID = #GenId
end try
begin catch
SET #ErrorNo = ERROR_NUMBER()
SET #ErrorMsg = ERROR_MESSAGE()
INSERT INTO Logging.dbo.ETL_Log (GenId, Startdate, Enddate, Process, Message, ErrorNo, Description)
VALUES (#GenId, #start, GETDATE(), #Process, #ErrorMsg, #ErrorNo,#Description)
end catch
GO
You invoke the function with 2 parameters (#GenId and #Description):
EXEC etl.etl_M_Update_Promo #GenID, #Description
However you have declared the function to take 1 argument:
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0
SQL Server is telling you that [etl_M_Update_Promo] only takes 1 parameter (#GenId)
You can alter the procedure to take two parameters by specifying #Description.
ALTER PROCEDURE [etl].[etl_M_Update_Promo]
#GenId bigint = 0,
#Description NVARCHAR(50)
AS
.... Rest of your code.
Use the following command before defining them:
cmd.Parameters.Clear()
This answer is based on the title and not the specific case in the original post.
I had an insert procedure that kept throwing this annoying error, and even though the error says, "procedure....has too many arguments specified," the fact is that the procedure did NOT have enough arguments.
The table had an incremental id column, and since it is incremental, I did not bother to add it as a variable/argument to the proc, but it turned out that it is needed, so I added it as #Id and viola like they say...it works.
For those who might have the same problem as me, I got this error when the DB I was using was actually master, and not the DB I should have been using.
Just put use [DBName] on the top of your script, or manually change the DB in use in the SQL Server Management Studio GUI.
Yet another cause of this error is when you are calling the stored procedure from code, and the parameter type in code does not match the type on the stored procedure.
I feel ashamed for even having to post this, but it might help someone in the future. Make sure you don't have a typo in your function call!
I kept getting this error trying to call a function and couldn't figure out why. My function and call had the same number of arguments (or so I thought).
Here's my function call:
SELECT FORMAT_NAME(A.LASTNAME, A.FIRSTNAME, A,MIDDLENAME)
It's easier to see in Stack Overflow, but it wasn't so obvious in SSMS that I had a comma in place of a period for A.MIDDLENAME.
SELECT FORMAT_NAME(A.LASTNAME, A.FIRSTNAME, A.MIDDLENAME)
Simple user error.
In addition to all the answers provided so far, another reason for causing this exception can happen when you are saving data from list to database using ADO.Net.
Many developers will mistakenly use for loop or foreach and leave the SqlCommand to execute outside the loop, to avoid that make sure that you have like this code sample for example:
public static void Save(List<myClass> listMyClass)
{
using (var Scope = new System.Transactions.TransactionScope())
{
if (listMyClass.Count > 0)
{
for (int i = 0; i < listMyClass.Count; i++)
{
SqlCommand cmd = new SqlCommand("dbo.SP_SaveChanges", myConnection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Clear();
cmd.Parameters.AddWithValue("#ID", listMyClass[i].ID);
cmd.Parameters.AddWithValue("#FirstName", listMyClass[i].FirstName);
cmd.Parameters.AddWithValue("#LastName", listMyClass[i].LastName);
try
{
myConnection.Open();
cmd.ExecuteNonQuery();
}
catch (SqlException sqe)
{
throw new Exception(sqe.Message);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
myConnection.Close();
}
}
}
else
{
throw new Exception("List is empty");
}
Scope.Complete();
}
}
You either have to double check the Parameters on both side (StoredProcedure And Code):
Make Sure they are the same on both ends regarding to the number of them.
Make Sure you have NOT changed your StoredProcedure code and forgot to Execute it, nothing bad happens if you hit F5 to make sure have all the changes committed and saved.
Make Sure you you have the same naming convention on both sides (Not Likely to be the cause but it worth a shot).
In SQL Server 2012 when I write code for stored procedure and for any function. After that when I want to alter it added extra blank line gap, that's why it seem very unacceptable lenghty..
CREATE proc sp_delete_Rte_article_admin_Latest
(
#id int
)
as
begin
if exists (select * from tblRte where Id=#id )
begin
declare #IvanID bigint
set #IvanID=(select [IvanArtId] from tblRte where Id=#id )
insert into tblRteOnDelete([IvanArtId],[StoryType],[ChannelType],[Filename],
[Headline],[PublishDate],[Title],[DocScope],[KeyWord],[Byline],[City],
[State],[StoryDate],[BodyContents],[DownloadedDate],DeleteDate)
select [IvanArtId],[StoryType],[ChannelType],[Filename],[Headline],[PublishDate],
[Title],[DocScope],[KeyWord],[Byline],[City],[State],[StoryDate],
[BodyContents],[DownloadedDate],GETDATE()
from tblIvanhoeXmlFeeds
where Id=#id
delete from tblRte where Id=#id
delete from tblUpdatedRteTopics where IvanArtId=#IvanID
delete from tblCheckAllowRte where ArticleID=#IvanID
delete from tblAddRteeApprove where ArticleID=#IvanID
return 1
end
else
begin
return 0
end
end
What should do for moving this for all time..any setting ?
I want to know Sqlserver 2012 Configuration Setting or Code Setting so that I could remove
the black Space Line ,which come after and after whern are going to alter and open again...
SO the exact error message I'm getting is:
The INSERT statement conflicted with the FOREIGN KEY constraint
"FK_featuredtype_featured". The conflict occurred in database
"docphin", table "dbo.featured", column 'featuredID'. The statement
has been terminated."
The part of my vb code that calls the sp that has the insert statement is:
If isChanged1.Checked Then
lq.admin_RemoveFeatured(isChanged.featuredID1)
lq.admin_AddFeatured(title1.Text, text1.Text, imageURL1.Text, login1.Checked, index1.Checked, mobile1.Checked, Integer.Parse(priority1.Text))
End If
If isChanged2.Checked Then
lq.admin_RemoveFeatured(isChanged.featuredID2)
lq.admin_AddFeatured(title2.Text, text2.Text, imageURL2.Text, login2.Checked, index2.Checked, mobile2.Checked, Integer.Parse(priority2.Text))
End If
Now the odd thing is when I execute admin_AddFeatured in sql server it works fine.
admin_RemoveFeatured:
CREATE PROCEDURE [dbo].[admin_RemoveFeatured]
-- Add the parameters for the stored procedure here
#featuredID int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
delete from featuredtype where featuredID= #featuredID
delete from featured where featuredID= #featuredID
END
GO
admin_AddFeatured:
CREATE PROCEDURE [dbo].[admin_AddFeatured]
-- Add the parameters for the stored procedure here
#title varchar(500) ,
#text varchar(MAX),
#imageURL varchar(200),
#loginPage bit,
#indexPage bit,
#mobilePage bit,
#priority int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
insert into featured
(title,text,imageURL, priority )
values
(#title,#text,#imageURL, #priority)
insert into featuredtype
(loginPage, indexPage, mobilePage)
values
(#loginPage, #indexPage, #mobilePage)
END
GO
I've been at this testing different solutions but I can't really seem to grasp what might be wrong here. My only thought is that ic could be related to how I get the ID field for each "feature" items that i'm inserting of deleting. For that I made a module:
Public Module isChanged
Public featuredID1 As Integer
Public featuredID2 As Integer
Public featuredID3 As Integer
Public featuredID4 As Integer
Public featuredID5 As Integer
Public featuredID6 As Integer
End Module
Then, in the page load sub I use an sp and read in the ID, like:
Dim lq2 As New lqDFDataContext
Dim var = lq2.admin_GetFeatured().ToList()
Dim i As Integer = 1
For Each f In var
If i = 1 Then
isChanged.featuredID1 = f.featuredID
title1.Text = f.title
text1.Text = f.text
imageURL1.Text = f.imageURL
login1.Checked = f.loginPage
index1.Checked = f.indexPage
mobile1.Checked = f.mobilePage
priority1.Text = Str(f.priority)
End If
etc...
You're not setting the featuredID in the featuredType table
try this
select #featuredID = Scope_Identity()
insert into featuredtype
(loginPage, indexPage, mobilePage,featuredID)
values
(#loginPage, #indexPage, #mobilePage, #featuredID)
All, I have the following query
IF NOT EXISTS (SELECT name
FROM sys.databases
WHERE name = N'Report')
BEGIN
DECLARE #DatabasePath NVARCHAR(1000);
SET #DatabasePath = (SELECT ResultMessage + '\'
FROM [Admin]..[Process]);
EXEC ispCREATEDB N'Report', #DatabasePath, N'10MB', N'20%'
END
ELSE
BEGIN
IF EXISTS (SELECT *
FROM Report.sys.objects
WHERE name = N'FatalErrSumm' AND type = N'U')
BEGIN
DROP TABLE [Report]..[FatalErrSumm];
CREATE TABLE [Report]..[FatalErrSumm]
(
[MDF] NVARCHAR(255) NULL,
[Error] INT NULL,
);
END
END
This checks if Report exists from a different databse; if it does not exist it creates it, if it does, it checks if table FatalErrSumm exists and if it does it drops and recreates it.
The problems is that it seems to be executing both possiblities of the IF NOT EXISTS block and giving the error
Msg 2702, Level 16, State 2, Line 24
Database 'Report' does not exist.
when the database Report does not exist. So it should never be entering the ELSE block, however it seems to be. This is very basic stuff, but I cannot for the life of me spot the error, What am I doing wrong here?
Thanks for your time.
You should bypass it using a dynamic sql
IF NOT EXISTS (SELECT name
FROM sys.databases
WHERE name = N'Report')
BEGIN
DECLARE #DatabasePath NVARCHAR(1000);
SET #DatabasePath = (SELECT ResultMessage + '\'
FROM [Admin]..[Process]);
EXEC ispCREATEDB N'Report', #DatabasePath, N'10MB', N'20%'
END
ELSE IF DB_ID('Report') IS NOT NULL
EXEC
(
'BEGIN
IF EXISTS (SELECT *
FROM Report.sys.objects
WHERE name = N''FatalErrSumm'' AND type = N''U'')
BEGIN
DROP TABLE [Report]..[FatalErrSumm];
CREATE TABLE [Report]..[FatalErrSumm]
(
[MDF] NVARCHAR(255) NULL,
[Error] INT NULL,
);
END
END'
);
I think dynamic sql is the good solution for that. because in compile time compiler checked that the database "report" is not exist in you server.
If the report is offline I think this failes, check if the database is online /attached. There is flag for this in the sys.databases table.
Also do not put your statements in the ELSE. If you enter the 'THEN' part you create the database. After that check if it is created. Than ALWAYS check for you FATALERRSUMM table and not from the IF.
pseudo code:
if (not exists database) -- watch it not exists is really NOT EXISTS not just not online
create the database
if (exists database and not online)
put online the database
if (not exists database or not online database)
throw error
if (exists table fatalerrsum)
drop table
create table