execute procedures from column in table - sql

Please help me with executing procedures in ORACLE.
I have table with 3 columns:
Create table PG_TABLE_1
(ID number(3),
PROCEDURE varchar2(15),
STATUS varchar2(4));
insert into PG_TABLE_1 values ('1','PROC_1','OK');
insert into PG_TABLE_1 values ('2','PROC_2','WAIT');
insert into PG_TABLE_1 values ('3','PROC_3','WAIT');
insert into PG_TABLE_1 values ('4','PROC_4','WAIT');
PROC_1, PROC_2, PROC_3, PROC_4 are names of real procedures.
How can I write code with LOOP, which:
get rows from TABLE_1 where STATUS='WAIT' ... so rows 2,3,4
choose first name of procedure (first smaller id) ... so "PROC_2"
execute PROC_2
change status in row 2 from "WAIT" to "OK"
and then PROC_3 etc.
Thank you for your help

Yup, I agree with #Anand you will have to make use of dynamic query
WHILE EXISTS (SELECT 1 FROM PG_TABLE_1 WHERE STATUS = 'WAIT')
BEGIN
SELECT TOP 1 #PROC = PROCEDURE FROM PG_TABLE_1 WHERE STATUS = 'WAIT'
SET #SQL = #SQL + #PROC
EXEC (#SQL)
UPDATE PG_TABLE_1 SET STATUS = 'OK' WHERE PROCEDURE = #PROC
END
Also please try to change the column names of Procedure and Status

Related

Microsoft SQL Server - default value provided by stored procedure

Is it possible to have a non-null column where the value is generated at insert by calling a stored procedure the parameters of which are values passed to insert into the row?
For example, I have table User:
| username | name | surname | id |
Insert looks like this:
INSERT INTO USER (username, name, surname)
VALUES ('myusername', 'myname', 'mysurname');
The id column is populated with an (integer) value retrieved by calling stored procedure mystoredproc with parameters myusername, myname, mysurname.
A further question is, would this stored procedure be called on each row, or can it be called in a grouped fashion. For example, I'd like my stored procedure to take the name and append a random integer to it so that that if I insert 100 users with the name 'David', they will get the same id and the stored procedure will be called only once. A bit of a bad example on the second point.
Good day,
Is it possible to have a non-null column where the value is generated at insert by calling a stored procedure
Option 1: please check if this work for you
Specify Default Value for the Column and use "NOT NULL"
create trigger on the table AFTER INSERT
Inside the trigger, you can use the virtual table "inserted" in order to get the inserted values.
Using these values (using the inserted table) you can update the column using the logic you need for all the rows at once
** there is no need to use external SP probably, but you can execute SP from trigger if needed
** All executed by a trigger is in the same transaction as the original query.
would this stored procedure be called on each row
NO! The trigger will be executed once for all rows you insert in the same statement. The inserted table includes all the rows which were inserted. In your update section (step 4) you can update all the rows which were inserted in once and no need to execute something for each row
** If you do use external SP which is executed from the trigger then you can pass it all the inserted table as one using Table-Valued Parameter
------------------- update ---------------
Here is a full example of using this logic:
drop table if exists T;
CREATE TABLE T (id int identity(2,2), c int NOT NULL default 1)
GO
CREATE TRIGGER tr ON T AFTER INSERT
AS BEGIN
SET NOCOUNT ON;
UPDATE T SET T.c = T2.C + 1
FROM inserted T2
INNER JOIN T T1 ON T1.id = T2.id
END
INSERT T(c) values (1) -- I insert the value 1 but the trigger will change it to 1+1=2
select * from T
GO
-- test multiple rows:
INSERT T(c) values (10),(20),(30),(40)
select * from T
GO
DECLARE #rc INT = 0,
#UserID INT = ABS(CHECKSUM(NEWID())) % 1000000 + 1;
WHILE #rc = 0
BEGIN
IF NOT EXISTS (SELECT 1 FROM dbo.Users WHERE UserId= #UserId)
BEGIN
INSERT dbo.Users(UserId) WHERE Username = #UserName SELECT #UserId;
SET #rc = 1;
END
ELSE
BEGIN
SELECT #UserId = ABS(CHECKSUM(NEWID())) % 1000000 + 1,
#rc = 0;
END
END

Insert trigger in SQL Server

I am trying to write a trigger that inserts in a log table the date, name of the table I inserted in, the name of the operation (insert, delete, update) and the number of insertion.
Here is my code:
CREATE TRIGGER [dbo].[Inser]
ON [dbo].[Avion]
AFTER INSERT
AS
BEGIN
DECLARE #codAv int
DECLARE #NumeAv varchar(100)
DECLARE #MotorAv varchar(100)
SELECT #codAv = INSERTED.codA FROM INSERTED
SELECT #NumeAv = INSERTED.NumeA FROM INSERTED
SELECT #MotorAv = INSERTED.Motor FROM INSERTED
SELECT ##ROWCOUNT AS INSERTED;
INSERT INTO LogM (DataM, Numele, Tipul, Numar)
VALUES(GETDATE(), 'Avion', 'Inserare', ##ROWCOUNT);
PRINT 'INSERT trigger fired.'
END
I have a stored procedure where I have something like 20 insertion of this type:
INSERT INTO Avion (Motor,NumeA)
VALUES ('Junkers','Focke-Wulf');
all separated from one another. When I run that code, the table LogM will be populated with 20 new rows of this type:
5 Nov 27 2016 8:58PM Avion Inserare 1.00
I want to make my trigger to count all the insertion stored in a procedure, then insert in LogM only one entry, with the ROWCOUNT not being 1.00, but the number of insertion I made in that stored procedure, and I don't have any idea how can I do this.
Thank you.
Instead of passing ##ROWCOUNT you can not just pass the ID?
##ROWCOUNT works to return the number of rows affected, as you enter one at a time, it will always be one.
CREATE TRIGGER [dbo].[Inser]
ON [dbo].[Avion]
AFTER INSERT
AS
BEGIN
DECLARE #codAv int
DECLARE #NumeAv varchar(100)
DECLARE #MotorAv varchar(100)
SELECT #codAv=INSERTED.codA FROM INSERTED
SELECT #NumeAv=INSERTED.NumeA FROM INSERTED
SELECT #MotorAv=INSERTED.Motor FROM INSERTED
INSERT INTO LogM
(DataM,Numele,Tipul,Numar)
VALUES(GETDATE(),'Avion','Inserare',#codAv);
PRINT 'INSERT trigger fired.'
END

Stored procedures - writing errors out to another table

I have two tables and a simple stored procedure. I want to use the stored procedure to insert into table1 with one of the parms being the primary key.
Here is where I am having trouble:
I want to have it so that if the parm/primary key the user has entered into the stored procedure and run is already on the table then it writes out the fields to a second table as well as the error description.
How do you capture / output this error information?
Stored procedure (sans the error logging):
CREATE PROCEDURE procedure1
#Primary INT,
#Info NVARCHAR
AS
BEGIN
SET NOCOUNT ON
INSERT INTO Table1
(
Primary ,
Info
)
VALUES
(
#Primary ,
#Info
)
END
Thanks
CREATE PROCEDURE dbo.InsertSomething
(
#PrimaryKey INT
, #Info NVARCHAR(MAX)
)
AS
BEGIN
IF EXISTS (SELECT 1 FROM dbo.Table1 WHERE ID = #PrimaryKey)
BEGIN
INSERT INTO dbo.Table2 (ID, Info)
VALUES (#PrimaryKey, #Info);
RAISERROR (15600,-1,-1, 'Your custom message');
END
ELSE
BEGIN
INSERT INTO dbo.Table1 (ID, Info)
VALUES (#PrimaryKey, #Info);
END
END
All you have to do is a simple check if record already exists in first table, and if it does just insert into it and throw error.

Insert data into table when i am using trigger?

Here is a trigger
CREATE TRIGGER [dbo].[CheckApplyId]
ON [dbo].[AppliedStudent_event] INSTEAD OF INSERT
AS
DECLARE #studentId INT
DECLARE #compReq_Id INT
BEGIN
SELECT #studentId = studentId
FROM INSERTED
SELECT #compReq_Id = compReq_Id
FROM INSERTED
IF EXISTS(SELECT StudentId,
compreq_id
FROM AppliedStudent_event
WHERE StudentId = #studentId
AND compreq_id = #compReq_Id)
BEGIN
ROLLBACK
PRINT 'User Already Applied'
END
END
When in insert a data into a table using command:
INSERT INTO AppliedStudent_event (StudentId, compreq_id)
VALUES (3026, 1)
Message is:
(1 row(s) affected)
But when I execute a sql command no data is inserted in the table.
Can you please tell why are you using trigger because you use only assign the variable #studentId and #compReq_Id from inserted table.
That's a broken trigger because inserted can contain multiple (or no) rows - so a statement like SELECT #ScalarVariable = column from inserted is always wrong.
And it's unnecessary since you can just place a UNIQUE constraint on the StudentId and compreq_id columns:
ALTER TABLE AppliedStudent_event
ADD CONSTRAINT UQ_Student_Events
UNIQUE (StudentId,compreq_id)
And it's further broken because you've specified it as an instead of trigger - that says that your code is going to be responsible for the actual insert - but your code doesn't actually do that. That's why no data ends up in the table.
If you insist on doing it as a trigger, it's actually tricky to get everything correct (that's why I'd really recommend the UNIQUE constraint). It'll end up being something like this:
CREATE TRIGGER [dbo].[CheckApplyId]
ON [dbo].[AppliedStudent_event] INSTEAD OF INSERT
AS
IF EXISTS(select
StudentId,compreq_id,COUNT(*)
from inserted
group by StudentId,compreq_id
HAVING COUNT(*) > 1)
OR EXISTS (select *
from inserted i
inner join
AppliedStudent_event e
on
i.StudentId = e.StudentId and
i.compreq_id = e.compreq_id)
BEGIN
ROLLBACK
PRINT 'User Already Applied'
END
ELSE
BEGIN
INSERT INTO AppliedStudent_event(StudentId,compreq_id /* Other columns? */)
SELECT StudentId,compreq_id /* And again, other columns */
FROM inserted
END

Updating a Table after some values are inserted into it in SQL Server 2008

I am trying to write a stored procedure in SQL Server 2008 which updates a table after some values are inserted into the table.
My stored procedure takes the values from a DMV and stores them in a table. In the same procedure after insert query, I have written an update query for the same table.
Insert results are populated fine, but the results of updates are getting lost.
But when I try to do only inserts in the stored procedure and I execute the update query manually everything is fine.
Why it is happening like this?
there should not be a problem in this.
below code working as expected.
create procedure dbo.test
as
begin
create table #temp (
name varchar(100) ,
id int
)
insert #temp
select name ,
id
from master..sysobjects
update #temp
set name='ALL Same'
from #temp
select * from #temp
drop table #temp
end
go
Best approach is to use Trigger, sample of AFTER UPDATE trigger is below:
ALTER TRIGGER [dbo].[tr_MyTriggerName]
ON [dbo].[MyTableName] AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
--if MyColumnName is updated the do..
IF UPDATE (MyColumnName)
BEGIN
UPDATE MyTableName
SET AnotherColumnInMyTable = someValue
FROM MyTableName
INNER JOIN Inserted
ON MyTableName.PrimaryKeyColumn = Inserted.PrimaryKeyColumn
END
END