Stored procedure for insert update and delete - asp.net

I am very new to stored procedures. I have a table with an Id auto increment. I want to insert, update and delete rows in my table.
What is wrong with my stored procedure?
CREATE PROCEDURE [dbo].[hrm_Languages]
(
#Name varchar(120),
#CreatedBy bigint=0,
#UpdatedBy bigint=0,
#IsDeleted bit=0
#ID int OUTPUT
)
AS
BEGIN
SELECT #ID = ISNULL(MAX(ID), 0) + 1
FROM [dbo].[Languages]
IF #StatementType = 'Insert'
BEGIN
insert into [dbo].[Languages] (Name, CreatedOn, UpdatedOn, CreatedBy, UpdatedBy, IsDeleted)
values(#Name, DateTime(), DateTime, #CreatedBy, #UpdatedBy, #IsDeleted)
SELECT #Name
WHERE NOT EXISTS (SELECT ID, NAME
FROM TableName
WHERE NAME = #Name)
BEGIN
END
END
IF #StatementType = 'Select'
BEGIN
select * from [dbo].[Languages]
END
IF #StatementType = 'Update'
BEGIN
UPDATE [dbo].[Languages]
SET Name = #Name, UpdateOn = DateTime()
WHERE ID = #ID
END
else IF #StatementType = 'Delete'
BEGIN
DELETE FROM [dbo].[Languages] WHERE ID = #ID
END
end
Getting these errors:
Msg 102, Level 15, State 1, Procedure hrm_Languages, Line 7
Incorrect syntax near '#ID'.
Msg 137, Level 15, State 1, Procedure hrm_Languages, Line 12
Must declare the scalar variable "#ID".
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 15
Must declare the scalar variable "#StatementType".
Msg 195, Level 15, State 10, Procedure hrm_Languages, Line 17
'DateTime' is not a recognized built-in function name.
Msg 156, Level 15, State 1, Procedure hrm_Languages, Line 24
Incorrect syntax near the keyword 'END'.
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 26
Must declare the scalar variable "#StatementType".
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 31
Must declare the scalar variable "#StatementType".
Msg 195, Level 15, State 10, Procedure hrm_Languages, Line 34
'DateTime' is not a recognized built-in function name.
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 38
Must declare the scalar variable "#StatementType".
Msg 137, Level 15, State 2, Procedure hrm_Languages, Line 40
Must declare the scalar variable "#ID".
I also want to show message on my web page using label that Name inserted, Nme deleted, NAme already exist

OK, problems with your sproc (after reading it again), please see comments:
-- If you worked for me, I'd be having words about this name, it does not state
-- what this sproc does.
CREATE PROCEDURE [dbo].[hrm_Languages]
(
#Name varchar(120),
#CreatedBy bigint=0,
#UpdatedBy bigint=0,
#IsDeleted bit=0, -- You need a comma here. You hadn't posted your errors when I answered
-- this site isn't really for fixing your compile errors... read
-- the error text, it's quite helpful. Something wrong on line 7...
#ID int OUTPUT
)
AS
BEGIN
-- Problem 1. You are selecting this ID prior to inserting. This won't always be the
-- ID inserted, if your system is getting heavy use.
SELECT #ID = ISNULL(MAX(ID), 0) + 1
FROM [dbo].[Languages]
-- Problem 2. You don't pass in #StatementType - this won't even compile.
IF #StatementType = 'Insert'
BEGIN
insert into [dbo].[Languages] (Name,CreatedOn,UpdatedOn,CreatedBy,UpdatedBy,IsDeleted)
values( #Name, DateTime(), DateTime, #CreatedBy, #UpdatedBy,#IsDeleted)
-- To get the inserted ID, do the following
SELECT #ID = SCOPE_IDENTITY()
-- Not sure what the following is for.
SELECT #Name
WHERE NOT EXISTS (SELECT ID,NAME FROM TableName
WHERE NAME=#Name)
BEGIN
END
END
-- This is where your sproc should end and the following should be three other sprocs.
IF #StatementType = 'Select'
BEGIN
select * from [dbo].[Languages]
END
-- Problem 3. You don't seem to be passing in and ID, just for output, and you set the ID in the
-- first line. If your system is heavily used, this might just end up updating a newly inserted
-- row, but most likely will update nothing.
-- Same goes for the delete below. Create separate sprocs for doing these things.
IF #StatementType = 'Update'
BEGIN
UPDATE [dbo].[Languages] SET
Name = #Name, UpdateOn= DateTime()
WHERE ID = #ID
END
else IF #StatementType = 'Delete'
BEGIN
DELETE FROM [dbo].[Languages] WHERE ID = #ID
END
end

In addition to the Paddy's Answer you must use GetDate() Instead of DateTime() to get the current DateTime.

I have corrected stored procedure syntactically. I have written comments for changes I have made. Correct sql will create SP for you.
CREATE PROCEDURE [dbo].[hrm_Languages]
(
#Name varchar(120),
#CreatedBy bigint=0,
#UpdatedBy bigint=0,
#IsDeleted bit=0, -- Insert comma
#StatementType Varchar(20), -- Add variable #StatementType
#ID int OUTPUT
)
AS
BEGIN
IF #StatementType = 'Insert'
BEGIN
-- As #ID will reset again after insertion of record so following two line are not needed
SELECT #ID = ISNULL(MAX(ID), 0) + 1
FROM [dbo].[Languages]
SELECT #Name
WHERE NOT EXISTS (SELECT ID,NAME FROM TableName -- What is table name for
WHERE NAME=#Name)
insert into [dbo].[Languages] (Name,CreatedOn,UpdatedOn,CreatedBy,UpdatedBy,IsDeleted)
values( #Name, SYSDATETIME(), SYSDATETIME(), #CreatedBy, #UpdatedBy,#IsDeleted)
-- SysDateTime is used to get current datetime
SELECT #ID = SCOPE_IDENTITY()
End
ELSE IF #StatementType = 'Select'
Begin
select * from [dbo].[Languages]
END
ELSE IF #StatementType = 'Update'
BEGIN
UPDATE [dbo].[Languages] SET
Name = #Name, UpdatedOn = SYSDATETIME()
WHERE ID = #ID
END
ELSE IF #StatementType = 'Delete'
BEGIN
DELETE FROM [dbo].[Languages] WHERE ID = #ID
END
END

Related

I want to use out parameter ,but I am not getting the proper syntax of doing so,:ORA-00900: invalid SQL statement

Problem definition: Create a procedure which will display the employees in descending order of employee name of
computer department.
CREATE OR REPLACE PROCEDURE pr_disp (name OUT VARCHAR2,
age OUT NUMBER,
dep OUT VARCHAR,
salary OUT NUMBER)
AS
CURSOR c
IS
SELECT name,
age,
department,
salary
FROM enployee2
WHERE department = 'Computer'
ORDER BY name DESC;
this_name enployee2.name%TYPE;
this_age enployee2.age%TYPE;
this_dep enployee2.department%TYPE;
this_sal enployee2.salary%TYPE;
BEGIN
OPEN c1;
LOOP
FETCH c1
INTO this_name,
this_age,
this_dep,
this_sal;
DBMS_OUTPUT.put_line (
this_name || ' ' || this_age || ' ' || this_dep || '
' || this_sal);
EXIT WHEN c1%NOTFOUND;
END LOOP;
CLOSE c1;
END;
/
Maybe there is a problem in my execution part...
execution part:
variable nm varchar2(50);
variable age number
variable dep varchar2(50);
variable sal number;
execute pr_disp(nm,age,dep,sal);
.The error comes when I execute the code is :ORA-00900: invalid SQL statement
Your code has several errors. Please see below to find out what and where:
Table Creation:
create table enployee2( name VARCHAR2(100),
age NUMBER,
department VARCHAR2(100),
salary NUMBER
);
INSERT INTO enployee2 VALUES ('AAA',32,'Computer',2344);
INSERT INTO enployee2 VALUES ('BBB',42,'Computer',4400);
insert into enployee2 values ('CCC',21,'Computer',2454);
Procedure:
Create OR REPLACE PROCEDURE pr_disp(
name OUT VARCHAR2,
age OUT NUMBER,
dep OUT VARCHAR,
salary OUT NUMBER)
AS
CURSOR c --<-- Your cursor name is `C` but you used it as `C1` below while opening and closing
IS
SELECT name,
age,
department,
salary
FROM enployee2
WHERE department ='Computer'
ORDER BY name DESC;
this_name enployee2.name%type;
this_age enployee2.age%type;
this_dep enployee2.department%type;
this_sal enployee2.salary%TYPE;
BEGIN
OPEN c; --<--Opening `C1` while your cursor name is `C`
LOOP
FETCH c INTO this_name,this_age,this_dep,this_sal;
dbms_output.put_line(this_name||' '||this_age||' '||this_dep||' '||this_sal);
EXIT WHEN c%NOTFOUND; --<--Exiting `C1` while your cursor name is `C`
END LOOP;
CLOSE c; --<--Closing `C1` while your cursor name is `C`
END;
/
Execution:
DECLARE
nm VARCHAR2(50);
age NUMBER;
dep VARCHAR2(50);
sal NUMBER;
BEGIN
pr_disp(nm,age,dep,sal);
END;
You have to write a PL/SQL-Block like this:
DECLARE
nm VARCHAR2 (50);
age NUMBER; -- here you were missing a semi-colon
dep VARCHAR2 (50);
sal NUMBER;
BEGIN
pr_disp (nm,
age,
dep,
sal);
END;
I would assume your stored procedure is invalid because of compilation errors. Try compiling again and check the messages.
You can also check the status with:
select status from user_objects where object_name='PR_DISP';
If it's INVALID you should be able to obtain error messages also via:
select * from user_errors where name = 'PR_DISP';
Maybe your table is named employee2 (not enployee2)?
Btw: What are the out parameters for? You never use them.

An unexpected token "EXCEPTION" was found In PL/SQL(DB2)

I am Wrting a Stored Function As below in db2.
CREATE OR replace FUNCTION moc_enddate( IN v_date VARCHAR(6),
IN v_message VARCHAR(20)) returns DATE
BEGIN
DECLARE v_temp DATE;
DECLARE v_end_date DATE;
DECLARE v_temp_string VARCHAR(8) DEFAULT '01';
SET v_temp_string = v_temp_string
|| v_date;
SET v_temp = to_date(v_temp_string,'DDMMYYYY');
SET v_end_date = (v_temp + 19 days);
RETURN v_end_date;
EXCEPTION
WHEN no_data_found THEN
SET v_message = 'SqlDataException';
WHEN OTHERS THEN
SET v_message = 'OTHER';
END;
But I am getting the following Exception.
ERROR [42601] [IBM][DB2/AIX64] SQL0104N An unexpected token "EXCEPTION" was found following "RN V_END_MOC_DATE; ". Expected tokens may include.
"<psm_case>".
Maybe, you are using DB2 SQL PL instead of PL/SQL. There is a difference between these languages. If it's the case, the following condition should work:
create or replace procedure CreatePlants
begin
declare sqlstate char(5) default '00000';
declare ErrorMsg varchar(96);
declare exit handler for sqlexception
begin
set ErrorMsg = 'SQLSTATE=' concat sqlstate;
signal sqlstate '99001'
set message_text = ErrorMsg;
end;
create table plants
( ID dec(3), Location varchar(16),
primary key (ID));
label on table plants is 'Plant master';
insert into plants values
( 1, 'Lost Angeles'),
( 2, 'New Yolk'),
( 3, 'Last Vegas');
end
For more references see:
Error Handling in SQL PL, Part 1
Determine The State Of The Error

Sequence and Trigger PL/SQL script for Automatic ID generation on a table

Can someone help me fix that code. It doesn´t run on PL/SQL (SQLPLUS #script.sql), giving
SP2-0552: Bind variable "NEW" not declared.
Script.SQL
prompt Creating Table SYSTEMDATALOG;
declare
counter1 integer;
counter2 integer;
begin
SELECT COUNT(*) INTO counter1 FROM ALL_TABLES WHERE TABLE_NAME='SYSTEMDATALOG' AND OWNER='MZMESDB';
if counter1 = 1 then
DROP TABLE SYSTEMDATALOG;
end if;
SELECT COUNT(*) INTO counter2 FROM ALL_SEQUENCES WHERE SEQUENCE NAME='SEQSYSTEMDATALOG';
if counter2 = 1 then
DROP SEQUENCE SEQSYSTEMDATALOGID;
endif;
CREATE TABLE "MZMESDB"."SYSTEMDATALOG" ( "ID" INTEGER NOT NULL ,
"DATETIME" DATE NOT NULL ,
"TYPE" VARCHAR2(64) NOT NULL,
"SEVERITY" INTEGER NOT NULL,
"SOURCE" VARCHAR2(64) NOT NULL,
"USER" VARCHAR2(64) NOT NULL,
"MESSAGE" VARCHAR2(1024), PRIMARY KEY ("ID") VALIDATE );
CREATE SEQUENCE SEQSYSTEMDATALOGID;
CREATE OR REPLACE TRIGGER TRIGSYSTEMDATALOGID
BEFORE INSERT ON SYSTEMDATALOG
FOR EACH ROW
BEGIN
SELECT SEQSYSTEMDATALOGID.NEXTVAL INTO :NEW.ID FROM DUAL;
END TRIGSYSTEMDATALOGID;
end;
/
Thanks in advance for any kind of help.
[DEFINITIVE CODE]
prompt Creating Table SYSTEMDATALOG;
declare
counter1 integer;
counter2 integer;
begin
SELECT COUNT(*) INTO counter1 FROM ALL_TABLES WHERE TABLE_NAME='SYSTEMDATALOG' AND OWNER='MZMESDB';
if counter1 = 1 then
execute immediate 'DROP TABLE SYSTEMDATALOG';
end if;
SELECT COUNT(*) INTO counter2 FROM ALL_SEQUENCES WHERE SEQUENCE_NAME='SEQSYSTEMDATALOG';
IF counter2 = 1 then
execute immediate 'DROP SEQUENCE SEQSYSTEMDATALOGID';
END IF;
execute immediate 'CREATE TABLE "MZMESDB"."SYSTEMDATALOG" (
"ID" INTEGER NOT NULL ,
"DATETIME" DATE NOT NULL ,
"TYPE" VARCHAR2(64) NOT NULL,
"SEVERITY" INTEGER NOT NULL,
"SOURCE" VARCHAR2(64) NOT NULL,
"USER" VARCHAR2(64) NOT NULL,
"MESSAGE" VARCHAR2(1024), PRIMARY KEY ("ID") VALIDATE )';
execute immediate 'CREATE SEQUENCE SEQSYSTEMDATALOGID';
execute immediate 'CREATE OR REPLACE TRIGGER TRIGSYSTEMDATALOGID
BEFORE INSERT ON SYSTEMDATALOG
FOR EACH ROW
BEGIN
SELECT SEQSYSTEMDATALOGID.NEXTVAL INTO :NEW.ID FROM DUAL;
END TRIGSYSTEMDATALOGID;';
end;
One problem is that you are mixing PL/SQL (an anonymous PL/SQL block) and DDL. While you can write DML statements (SELECT/INSERT/UPDATE/DELETE) in PL/SQL you cannot write DDL (CREATE/DROP etc) directly in PL/SQL.
You need to either run your DDL statements outside the anonymous PL/SQL block or use
EXECUTE IMMEDIATE '<statement>';.
As for the error on :NEW I think it will disappear when you fix the other issue. If it doesn't, try adding:
SET SCAN OFF
In the beginning of your SQL*PlUS file.

SQL use comma-separated values with IN clause

I am developing an ASP.NET application and passing a string value like "1,2,3,4" into a procedure to select those values which are IN (1,2,3,4) but its saying "Conversion failed when converting the varchar value '1,2,3,4' to data type int."
Here is the aspx code:
private void fillRoles()
{
/*Read in User Profile Data from database */
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand("sp_getUserRoles");
db.AddInParameter(cmd, "#pGroupIDs", System.Data.DbType.String);
db.SetParameterValue(cmd, "#pGroupIDs", "1,2,3,4");
IDataReader reader = db.ExecuteReader(cmd);
DropDownListRole.DataTextField = "Group";
DropDownListRole.DataValueField = "ID";
while (reader.Read())
{
DropDownListRole.Items.Add((new ListItem(reader[1].ToString(), reader[0].ToString())));
}
reader.Close();
}
Here is my procedure:
CREATE Procedure [dbo].[sp_getUserRoles](#pGroupIDs varchar(50))
AS BEGIN
SELECT * FROM CheckList_Groups Where id in (#pGroupIDs)
END
Here is a workaround I found to do what you are trying to achieve
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
SELECT * FROM CheckList_Groups Where (',' + #pGroupIDs +',' LIKE '%,' + CONVERT(VARCHAR, id) + ',%')
End
This gets your comma delimited list and compares it to the id's(which are represented like so ',1,', ',2,' etc) in the table using LIKE
If you dont want to use dynamic sql, the best way ive found is to create a function which turns a delimited string into a table, something like this works for an Integer list:
CREATE FUNCTION [dbo].[StringToIntList]
(#str VARCHAR (MAX), #delimeter CHAR (1))
RETURNS
#result TABLE (
[ID] INT NULL)
AS
BEGIN
DECLARE #x XML
SET #x = '<t>' + REPLACE(#str, #delimeter, '</t><t>') + '</t>'
INSERT INTO #result
SELECT DISTINCT x.i.value('.', 'int') AS token
FROM #x.nodes('//t') x(i)
ORDER BY 1
RETURN
END
Then use that in your sp:
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
SELECT * FROM CheckList_Groups Where id in (
SELECT ID FROM dbo.StringToIntList(#pGroupIds,',')
)
End
Sure it can't do that,
The generated query would be sth like this
SELECT * FROM CheckList_Groups Where id in ('1,2,3,4')
and sure it can't be executed.
you can build the query in your stored procedure then execute it with exec
'SELECT * FROM CheckList_Groups Where id in (' + #pGroupIDs + ')'
or
SELECT * FROM CheckList_Groups Where charindex(','+id+',' , #pGroupIDs)>0
but you first must add the ',' to start and end of your parameter in your c# code
It is not possible to put those values (the comma separated string) in a parameter-value.
What you'll have to do, is to create the SQL Statement in your stored procedure dynamically, by string concatenation. You'll have to execute it with the sp_executesql stored procedure then.
CREATE PROCEDURE [dbo].[getUserRoles]( #groupIds NVARCHAR(50) )
AS BEGIN
DECLARE #statement NVARCHAR(255)
SELECT #statement = N'SELECT * FROM CheckList_Groups Where id in ( ' + #pGroupIDs + N')'
execute sp_executesql #statement
END
Also, not that I named the SP getUserRoles instead of sp_getUserRoles.
The reason is very simple: when you execute a stored procedure whose name starts with sp_, then SQL Server will first query the master database to find that stored procedure, which causes a performance hit offcourse.
The way you are trying to do this is slightly wrong. You will need to use EXECUTE in order to achieve this.
CREATE PROCEDURE [dbo].[sp_getUserRoles](#pGroupIDs nvarchar(50))
As
BEGIN
EXECUTE (N'SELECT * FROM CheckList_Groups Where id in (' + #pGroupIDs + ')';
END
DECLARE #TagId NVARCHAR(100) = '43,81'
SELECT * FROM TABLE WHERE TagId IN (SELECT TRIM(VALUE) FROM STRING_SPLIT( #TagId , ',' ) )
USE STRING_SPLIT FUNCTION FOR THIS
You need to use SP_executesql to achieve this functionllity
CREATE Procedure [dbo].[sp_getUserRoles](
#pGroupIDs varchar(50)
)
As
BEGIN
EXECUTE sp_executesql
N'SELECT * FROM CheckList_Groups Where id in (#pGroupIDs)',
N'#level varchar(50)',
#level = #pGroupIDs;
End
The IN clause can't take a bound parameter like that. What it's being given when the query is actually created is SELECT * FROM CheckList_Groups Where id in ('1,2,3,4'). Essentially the IN clause is being passed a single string.
First create function -
Just run this code
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[CSVToTable] (#InStr VARCHAR(MAX))
RETURNS #TempTab TABLE
(id int not null)
AS
BEGIN
;-- Ensure input ends with comma
SET #InStr = REPLACE(#InStr + ',', ',,', ',')
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
WHILE PATINDEX('%,%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%,%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #TempTab(id) VALUES (#VALUE)
END
RETURN
END
GO
Then -
Use function in bracket with select statment -
DECLARE #LIST VARCHAR(200)
SET #LIST = '1,3'
SELECT Id, Descr FROM CSVDemo WHERE Id IN (SELECT * FROM dbo.CSVToTable(#LIST))

Msg 512, Level 16, State 1, Procedure test, Line 21 Subquery returned more than 1 value

ALTER PROCEDURE [dbo].[test]
#tour int,
#tourname varchar(50) OUTPUT,
#tourdepartures varchar(50) OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SET #tourname = (select [tour name] from dbo.products1 where tour = #tour)
SET #tourdepartures = (select ddate7 from dbo.TDEPART1 where tour = #tour and depart > convert(int,getdate()))
END
I want to use a stored procedure to populate a label on my asp.net page
and a dropdownlist
#tourname will be populated into a single label
while #tourdepartures will be multiple dates, that i want in a dropdownlist
however when i run my sp i get this error
Msg 512, Level 16, State 1, Procedure test, Line 21
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
(1 row(s) affected)
(1 row(s) affected)
and it works when i do
ALTER PROCEDURE [dbo].[test]
#tour int,
#tourname varchar(50) OUTPUT,
#tourdepartures varchar(50) OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SET #tourname = (select [tour name] from dbo.product where tour = #tour)
SET #tourdepartures = (select top 1 ddate7 from abcfilestest.dbo.TDEPART where tour = #tour and depart > convert(int,getdate()))
END
but it only gives me the first departure date
Get rid of the second SET and just return a resultset that you can use a reader with:
ALTER PROCEDURE [dbo].[test]
#tour int,
#tourname varchar(50) OUTPUT
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
SET #tourname = (select [tour name] from dbo.products where tour = #tour)
select ddate7 from abcfilestest.dbo.TDEPART where tour = #tour and depart > convert(int,getdate())
END
You can try this to remove the error, but I don't think it's really what you want:
-- Insert statements for procedure here
SET #tourname = (select TOP 1 [tour name] from dbo.products where tour = #tour)
SET #tourdepartures = (select TOP 1 ddate7 from abcfilestest.dbo.TDEPART where tour = #tour and depart > convert(int,getdate()))
If you really want a list of all of the tour dates, change the last statement to
select ddate7 from abcfilestest.dbo.TDEPART where tour = #tour and depart > convert(int,getdate())
and parse the result set on the client as you usually would.
Also, for the love of all that's holy, rename that ddate7 column to something meaningful.
A scalar variable can only hold one value. The query you are using returns more than one value. YOu have several choices and the right one depends on your situation.
If you only want the latest date, use top 1 and order by date desc in your select.
If you want all the dates, then use a table variable not a scalar variable. I know I can use table variable in SQL Server 2008 as stored procedure parameter, not sure about 2005. You could just return 2 recordsets (so that you are consistent in what you are returning) or one output variable and one select instead of using output variables.

Resources