When I try to call the procedure with call insertp_detail ('P005','02','T001','CAT2') , it will show the error :
SQL0811N The result of a scalar fullselect, SELECT INTO statement, or
VALUES INTO statement is more than one row. SQLSTATE=21000
The expected result that I want with this procedure is to insert the values into purchase_detail table.
CREATE PROCEDURE insertp_detail
(IN purchase_id char(4), seat_id char(2), trans_id char(4), seat_type varchar(5))
BEGIN
IF ((SELECT COUNT(trans_id)
FROM purchase_detail
GROUP BY trans_id) < 3)
THEN INSERT into purchase_detail values(purchase_id, seat_id, trans_id, seat_type);
end if;
end
This is correct. You have a group by which generally returns multiple rows. Presumably you intend to count the number of rows only for the trans_id provided as an argument to the stored procedure:
CREATE PROCEDURE insertp_detail (
IN in_purchase_id char(4),
IN in_seat_id char(2),
IN in_trans_id char(4),
IN in_seat_type varchar(5)
)
BEGIN
IF ((SELECT COUNT(*)
FROM purchase_detail
WHERE pd.trans_id = in_trans_id
) < 3)
THEN
INSERT INTO purchase_detail
VALUES (in_purchase_id, in_seat_id, in_trans_id, in_seat_type);
END IF;
END;
Note that the parameters to the stored procedure have prefixes to distinguish them from column names.
You should also list the columns for purchase_detail for the INSERT statement.
Related
I am implementing a library management system in SQL. I have the following table structure and some values inserted in them:
create table books
(
IdBook number(5),
NameBook varchar2(35),
primary key(IdBook)
);
create table users
(
IdUsers number(5),
NameUser varchar2(20),
primary key(IdUsers)
);
create table borrowed
(
IdBorrowed number(5),
IdUsers number(5),
IdBook number(5),
DueDate date,
DateReturned date,
constraint fk_borrowed foreign key(IdUsers) references users(IdUsers),
constraint fk_borrowed2 foreign key(IdBook) references books(IdBook)
);
insert into books values(0,'FairyTale');
insert into books values(1,'Crime and Punishment');
insert into books values(2,'Anna Karenina');
insert into books values(3,'Norwegian Wood');
insert into users values(01,'Robb Dora');
insert into users values(02,'Pop Alina');
insert into users values(03,'Grozavescu Teodor');
insert into users values(04,'Popa Alin');
insert into borrowed values(10,02,3,'22-Jan-2017',null);
insert into borrowed values(11,01,1,'25-Jan-2017','19-Dec-2016');
insert into borrowed values(12,01,3,'22-Jan-2017',null);
insert into borrowed values(13,04,2,'22-Jan-2017','13-Dec-2016');
What I want now is that my db to allow "borrowing" books for the users(i.e insert into the borrowed table) that have no unreturned books(i.e date returned is not null) and if they have unreturned books I want to abandon the whole process. I thought to implement this in the following way:
create or replace procedure borrowBook(IdBorrowed in number,IdUsers number,IdBook number,DueDate date,DateReturned date) as begin
if exists (SELECT u.IdUsers, u.NameUser, b.DateReturned
FROM users u, borrowed b
WHERE u.IDUSERS = b.IdUsers and DateReturned is not null),
insert into borrowed values(IdBorrowed,IdUsers,IdBook,DueDate,DateReturned);
end borrowBook;
The above procedure does not check if the parameter I pass to this function is the same as the one in my select and I do not know how to do this and correctly insert a value in my table.
Any help would be much appreciated. Thank in advance!
You should not name your parameters the same as columns also used inside the procedure.
You can also simplify your procedure to a single INSERT statement, no IF required:
create or replace procedure borrowBook(p_idborrowed in number, p_idusers number, p_idbook number, p_duedate date, p_datereturned date)
as
begin
insert into borrowed (idborrowed, idusers, idbook, duedate, datereturned)
select p_idborrowed, p_idusers, p_idbook, p_duedate, p_datereturned
from dual
where not exists (select *
from users u
join borrowed b on u.idusers = b.idusers
and b.datereturned is not null);
end borrowBook;
It's also good coding style to explicitly list the columns for an INSERT statement. And you should get used to the explicit JOIN operator instead of using implicit joins in the where clause.
What about this one:
create or replace procedure borrowBook( p_IdBorrowed in number ,
p_IdUsers number ,
p_IdBook number ,
p_DueDate date ,
p_DateReturned date )
as
begin
if (SELECT COUNT(*)
FROM borrowed
WHERE IDUSERS = p_IdUsers
AND DateReturned IS NULL) = 0 THEN
insert into borrowed values (p_IdBorrowed ,
p_IdUsers ,
p_IdBook ,
p_DueDate ,
p_DateReturned );
end if ;
end borrowBook;
You would seem to want something like this:
create or replace procedure borrowBook (
in_IdBorrowed in number,
in_IdUsers number,
in_IdBook number,
in_DueDate date,
in_DateReturned date
) as
v_flag number;
begin
select (case when exists (select 1
from borrowed b
where b.IdUsers = in_IdUsers and b.DateReturned is not null
)
then 1 else 0
end)
into v_flag
from dual;
if (flag = 0) then
insert into borrowed
values(in_IdBorrowed, in_IdUsers, in_IdBook, in_DueDate, v_DateReturned);
end if
end -- borrowBook;
I have two select statements in my stored procedure:
alter proc multiple
select * from table-one
select * from table-two
Now how to get the data of table-one only by executing the stored procedure?
You can pass input variable and use if statment. For example:
ALTER PROCEDURE multiple
#choice INT
AS
BEGIN
IF (#choice = 1)
BEGIN
SELECT * FROM Table1
END
IF (#choice = 2)
BEGIN
SELECT * FROM Table2
END
IF (#choice = 3)
BEGIN
SELECT * FROM Table1
SELECT * FROM Table2
END
END
And execution of procedure:
EXECUTE multiple #choice = 1 -- to use 1st select
EXECUTE multiple #choice = 2 -- to use 2st select
EXECUTE multiple #choice = 3 -- to use both selects
You can use TEMP table to fill all result in the temp table.
if you have 3 table name tab_1,tab_2,tab_3 then create a temp table with column maximum from these table(tab_1,tab_2,tab_3) and add a extra column to temp table to identify data from tables.
tab_1(id bigint,name varchar(50))
tab_2(id bigint,email varchar(50))
tab_3(id bigint,address varchar(50),phone varchar(50))
then your temp table should be like this
#tmp(col1 bigint(),col2 varchar(50),col3 varchar(50),from_table varchar(50))
e.g
create table tab_1
(
id bigint identity(1,1),
name varchar(50),
email varchar(50)
)
insert into tab_1(name,email) values
('a','a#mail.com'), ('b','c#mail.com'),
('a1','a1#mail.com'), ('a2','a2#mail.com'),
('a3','a3#mail.com'), ('a4','a4#mail.com'),
('b1','b1#mail.com'),('b2','b2#mail.com')
create table tab_2
(
id bigint identity(1,1),
name varchar(50),
email varchar(50),
amount decimal(18,2)
)
insert into tab_2(name,email,amount) values
('a','a#mail.com',12.5), ('b','c#mail.com',11.6),
('a1','a1#mail.com',11.7), ('a2','a2#mail.com',88.9),
('a3','a3#mail.com',90), ('a4','a4#mail.com',45),
('b1','b1#mail.com',78),('b2','b2#mail.com',88)
and the Sp should be like
create table #tab(col1 bigint,
col2 varchar(50),
col3 varchar(50),col4 varchar(50),table_from varchar(50))
insert into #tab(col1,col2,col3,table_from)
select id,name,email,'table_1' from tab_1
insert into #tab(col1,col2,col3,col4,table_from)
select id,name,email,amount,'table_2' from tab_2
select * from #tab
FIDDLE DEMO
The table tblEffort has 3 columns EmployeeName, Effort, Date. I get the first 2 column values from a table type parameter and have to insert a common date for all these values.
do not have the option to include timesheetdate in dtCSV
There should be some other way than running an update again on the inserted columns right?
The below code gives the error - Must declare the table variable "#TimesheetDate"
CREATE TYPE dbo.SaveEffort_TableType AS TABLE
(
EmployeeName varchar(200),
Effort decimal(18,2)
);
GO
CREATE PROCEDURE SaveEmployeeEffort
(
#TimesheetDate datetime,
#dtCSV AS dbo.SaveEffort_TableType readonly
)
AS
BEGIN
INSERT INTO tblEffort(EmployeeName,Effort,[Date])
SELECT * FROM #dtCSV,#TimesheetDate
END
You need to put the variable into the SELECT clause, not the FROM clause
CREATE PROCEDURE SaveEmployeeEffort
(
#TimesheetDate datetime,
#dtCSV AS dbo.SaveEffort_TableType readonly
)
AS
BEGIN
INSERT INTO tblEffort(EmployeeName,Effort,[Date])
SELECT EmployeeName,Effort, #TimesheetDate FROM #dtCSV
END
I have the following stored procedure which we use to insert data into a table:
CREATE OR REPLACE PROCEDURE mySproc
(
invoiceId IN NUMBER
customerId IN NUMBER
)
IS
BEGIN
INSERT INTO myTable (INVOICE_ID)
VALUES (invoiceId);
END mySproc;
/
What I am trying to do is to get the last inserted ID (this is the primary key field on myTable and auto incremented using a sequence) and insert it into another table, I have tried the following but could not get it working:
CREATE OR REPLACE PROCEDURE mySproc
(
invoiceId IN NUMBER
customerId IN NUMBER
)
IS
BEGIN
INSERT INTO myTable (INVOICE_ID)
VALUES (invoiceId)
returning id into v_id;
INSERT INTO anotherTable (ID, customerID)
VALUES (v_id, customerId);
END mySproc;
/
I am getting this error: [Error] PLS-00049 (59: 26): PLS-00049: bad bind variable 'V_ID' I think I need to declare v_id somewhere but I tried before and after the BEGIN statement but that gave another error.
Any ideas as to how to do this?
Thanks
Change your procedure to
CREATE OR REPLACE PROCEDURE mySproc
(
invoiceId IN NUMBER, -- Added comma
customerId IN NUMBER
)
IS
v_id NUMBER; -- ADDED
BEGIN
INSERT INTO myTable (INVOICE_ID)
VALUES (invoiceId)
returning id into v_id;
INSERT INTO anotherTable (ID, customerID)
VALUES (v_id, customerId);
END mySproc;
Share and enjoy.
what i want to achieve is i have a table called orders.
i want to perform the before insert trigger on my orders table.i want to capture the
username of person performing INSERT into table.
one table called info which contain the user.
this is my code
create table orders
(
order_id int,
quantity int,
cost int,
total_cost int,
created_date datetime,
created_by varchar(20)
)
create trigger beforeInsertdata
before insert
on orders
for each row
declare
v_username varchar2(10);
begin
-- Find username of person performing INSERT into table
SELECT user INTO v_username
FROM info;
-- Update create_date field to current system date
:new.create_date := sysdate;
-- Update created_by field to the username of the person performing the INSERT
:new.created_by := v_username;
END;
--user information--
create table info
(
userid int ,
user_name varchar(10)
)
insert into info values(1,'vivek')
select * from info
Basically, triggers are classified into two main types:-
1)After Triggers (For Triggers)
2)Instead Of Triggers
and the syntax for trigger is
CREATE TRIGGER trigger_name ON table_name
[FOR|AFTER|INSTEAD OF] [INSERT|UPDATE|DELETE]
AS
//your code goes here
GO
NOTE : FOR keyword used for INSERT |UPDATE Command where as AFTER USED FOR DELETE Command.
It's hard to tell what you're really trying to do. I've modified your code sample so that it will work on SQL2K5 and made some assumptions about how you're wanting to use the connected user account.
CREATE TABLE orders (
order_id int,
quantity int,
cost int,
total_cost int,
created_date datetime,
created_by varchar(20)
);
CREATE TABLE info (
userid int,
user_name varchar(10)
);
INSERT INTO info
VALUES (1, 'vivek');
SELECT *
FROM info;
CREATE TRIGGER orders_InsteadOfInsert ON orders
INSTEAD OF INSERT AS BEGIN
SET NOCOUNT ON;
-- varchar(10) is to match your table, but probably should be larger
DECLARE #CurrentUser VarChar(10);
SELECT #CurrentUser = SYSTEM_USER;
IF (#CurrentUser NOT IN (SELECT user_name FROM info)) BEGIN
-- consider using an identity column for the key instead of this
INSERT INTO info (userid, user_name)
SELECT
ISNULL((SELECT MAX(userid) FROM info), 0) + 1,
#CurrentUser;
END;
INSERT INTO orders (order_id, quantity, cost, total_cost, created_date, created_by)
SELECT
INS.order_id,
INS.quantity,
INS.cost,
INS.total_cost,
GETDATE(),
#CurrentUser
FROM INSERTED INS;
END;