How to update particular column dynamically - plsql

I'm using the following table
book_Catalog contains
book name,
book_id,
book_title,
created_by(contains the detail which user created this entry),
updated_by(contains the detail which user updates this entry)
created_by column uses the system date
Please give an idea
what query should be used to fill the update_by column??
Thanks in advance,
Ashmitha

You can use something like
CREATE PROCEDURE UPDATE_BOOK_CATALOG_UPDATED_BY
(pin_BOOK_ID BOOK_CATALOG.UPDATED_BY%TYPE)
IS
BEGIN
UPDATE BOOK_CATALOG
SET UPDATED_BY = UID
WHERE BOOK_ID = pin_BOOK_ID;
END UPDATE_BOOK_CATALOG_UPDATED_BY;
Share and enjoy.

You can use AFTER UPDATE TRIGGER to do this.
CREATE OR REPLACE TRIGGER My_Trigger
AFTER INSERT
ON TABLE
FOR EACH ROW
DECLARE
BEGIN
END;/

Related

PL/SQL Trigger exercise

I have this question that I can see what it's asking but just can't wrap my head around how to write it specifically:
When a new tuple is inserted into the sales order detail, your trigger should insert a corresponding raw material tuple in the Inventory Report table for the Report date (i.e., beginning inventory level, consumption quantity, same-day order quantity, next-day order quantity)
Assumptions I gathered from the notes:
itemID = itemID from RAWMATERIALS table
reportDate = dueDate from SALESORDERS table
begInv = inventoryLevels from RAWMATERIALS table
consumpQty = itemID from FINISHEDGOODS * rmQuantity (raw material required to make each finished good) from FINISHED GOODS
orderNextDay = If consumpQty <= begInv then orderNextDay = consumpQty
orderSameDay = 0
orderSameDay = If consumpQty > begInv then orderNextDay = begInv
orderSameDay = consumpQty - begInv
I thought the trigger might go something like:
CREATE OR REPLACE TRIGGER inv_report
BEFORE INSERT
ON SALESORDERDETAIL
FOR EACH ROW
DECLARE
item_id RAWMATERIALS.ITEMID%TYPE
reportDate SALESORDERS.DUEDATE%TYPE
begInv RAWMATERIALS.INVENTORYLEVEL%TYPE
And then I understand we would probably need to INSERT into INVENTORYREPORT table (which currently has no data in it) and maybe do an IF ELSEIF statement to satisfy the orderNextDay and orderSameDay columns but i'm still not familiar enough with PL/SQL to know exactly how to tackle this.
Can anyone help me out with this? Thanks!
I'll try to find some time to write up some code for you on this, but my first recommendation is to NOT do this in a trigger. Instead, create a procedure "insert_so_detail" that inserts into the the SALESORDERDETAIL and then does the related insert into INVENTORYREPORT.
That procedure is then always called to insert into the S-O-D table. Executing DML inside triggers is a tricky thing to do because the database might decide it needs to restart the DML and then possibly do another insert into the I-R table. Check out this AskTOM thread for more details.
You are always better off putting your DML into PL/SQL package APIs, then only allow DML on the table through the API (grant execute on the package, do NOT grant insert or update or delete on the table directly to a user).

Denormalization - maintaining redundancy by using triggers in Oracle

I have a task for my university project where I have denormalized a table and now I have to implement a trigger in order to maintain redundancy. After following the book accordingly I'm stuck on the last step and I can't get my mind around it.
I have two tables - Supplier and Catalogue
**Supplier**
SupplierCode (primary key)
SupplierName
**Catalogue**
SupplierCode (foreign key)
CatalogueCode (both SupplierCode and CatalogueCode form a primary key)
CatalogueName
DateCreated
SupplierName (redundant column for denorm purposes)
When a new row is inserted in the Catalogue table I want that SupplierName field in the same table gets populated based on the SupplierCode which was inserted.
What I have so far:
We need to create a package as well
create or replace PACKAGE "PACK" AS
SUPPCODE NUMBER:=0;
SUPPNAME VARCHAR2(50);
END;
I have created a BEFORE INSERT TRIGGER on Catalogue table
create or replace TRIGGER CatalogueBefore
BEFORE INSERT OR UPDATE ON CATALOGUE
FOR EACH ROW
BEGIN
PACK.SUPPCODE:=:NEW.SUPPLIERCODE;
END;
I've then added an AFTER INSERT TRIGGER on Catalogue table
create or replace TRIGGER "AddNewCatalogue"
AFTER INSERT ON CATALOGUE
FOR EACH ROW
DECLARE
V_SUPPNAME SUPPLIER.SUPPLIERNAME%TYPE;
BEGIN
SELECT SUPPLIERNAME INTO V_SUPPNAME
FROM SUPPLIER
WHERE SUPPLIERCODE= PACK.SUPPCODE;
PACK.SUPPNAME:=V_SUPPNAME;
END;
After all of this I have the Supplier name held in my package in PACK.SUPPNAME but my question is how do I now use this variable when inserting a new row in the Catalogue table? I'm stuck at this for some time now and I'm probably missing something obvious. :) Any help is appreciated. Thanks.
P.S Please ignore uppercase vs. lowercase letters - I've just translated the names from my native language. :)
Thanks
I have denormalized a table and now I have to implement a trigger in order to maintain redundancy
[...]
When a new row is inserted in the Catalogue table I want that SupplierName field in the same table gets populated based on the SupplierCode which was inserted.
If those are your only requirements, all you need is one trigger to alter the record with the data from the second table. Something like that, maybe:
CREATE OR REPLACE TRIGGER CatalogueBefore
BEFORE INSERT OR UPDATE ON Catalogue
FOR EACH ROW
BEGIN
SELECT S.SupplierCode INTO :NEW.SupplierCode
FROM Supplier S
WHERE S.SupplierName = :NEW.SupplierName;
END;
That way, on update or insert into the table Catalogue, the SupplierCode will be overwritten by the code coming from Supplier table. See http://sqlfiddle.com/#!4/d79e0/1 for a live example.
Some notes though:
For this to work, Supplier.SupplierName should be an unique index too. In fact, the all thing is based on the assumption this is a natural key.
You very probably need an other trigger to deal with updates in the Supplier table. Say, when one supplier's name will change, the new name will have to be propagated to Catalogue.

How do you write a good stored procedure for update?

I want to write a stored procedure (SQL server 2008r2), say I have a table:
person
Columns:
Id int (pk)
Date_of_birth date not null
Phone int allow null
Address int allow null
Name nvarchat(50) not null
Sample data:
Id=1,Date_of_birth=01/01/1987,phone=88888888,address=null,name='Steve'
Update statement in Stored procedure, assume
The parameters are already declare:
Update person set
Date_of_birth=#dob,phone=#phone,address=#address,name=#name where id=#id
The table has a trigger to log any changes.
Now I have an asp.net update page for updating the above person table
The question is, if user just want to update address='apple street' , the above update statement will update all the fields but not check if the original value = new value, then ignore this field and then check the next field. So my log table will log all the event even the columns are not going to be updated.
At this point, my solutions
Select all the value by id and store them into local variables.
Using if-else check and generate the update statement. At last,
dynamically run the generated SQL (sp_executesql)
Select all the value by id and store them into local variables.
Using if-else check and update each field seperately:
If #dob <> #ori_dob
Begin
Update person set date_of_birth=#dob where id=#id
End
May be this is a stupid question but please advice me if you have better idea, thanks!
This is an answer to a comment by the OP and does not address the original question. It would, however, be a rather ugly comment.
You can use a statement like this to find the changes to Address within an UPDATE trigger:
select i.Id, d.Address as OldAddress, i.Address as NewAddress
from inserted as i inner join
deleted as d on d.Id = i.Id
where d.Address <> i.Address
One such statement would be needed for each column that you want to log.
You could accumulate the results of the SELECTs into a single table variable, then summarize the results for each Id. Or you can use INSERT/SELECT to save the results directly to your log table.

Check for duplicates in the table before inserting data into SQL Server with ASP.NET

I have got 3 columns in the table, I need to check the email field before insertion of new row, so if the email exist, it should not insert that row. Do I have to go through 2 queries to achieve that, so for instance first check :
Select count(*) FROM PRODUCT WHERE email = #email
AND THEN RUN AN INSERT
Insert INTO PRODUCT (....) VALUES (....)
Or is there any better way to achieve that ,
Any suggestions or advice will be appreciated .
Thanks
You can have an INSERT statement that checks for the condition, and only inserts something, if it doesn't already exist:
IF NOT EXISTS (SELECT * FROM dbo.Product WHERE email = #email)
INSERT INTO dbo.Product(list of columns)
VALUES(list of values)
As marc_s mentioned you may use a conditional insert into. On the other hand, using a unique constraint on your email column may be very helpful too!
Just think of the possibility to insert data without your application. There would be no rule to avoid the same email!
CREATE TABLE Product
(
xxx int NOT NULL,
xxx xxx xxx,
UNIQUE (email)
)
Just google for alter/create table(s) with unique constraints!

is there a command for "AS" in postgres?

I'm wondering if there is a command like AS for postgres. Does anyone know if postges has this ability? I've tried to google it but it's a very difficult question to google :P I want to make a select statement and store it as a new table name. I want to say something like:
select subj, user as 'new' from table_name;
Yes. It's a reserved SQL key word in PostgreSQL. See Table C-1 at the linked documentation page.
It's typically used with column labels.
The AS keyword is optional, but only if the new column name does not
match any PostgreSQL keyword (see Appendix C).
CREATE TABLE new_table AS SELECT subj, user FROM table_name
So, your new table will be ready.
"I want to make a select statement and store it as a new table name" --
CREATE VIEW view_name AS
SELECT subj, user AS "new" FROM table_name;
If you don't want to leave any changes in the schema, you can do something like this-
select new.* from (
select foo, bar from old
) as new
develop your query: SELECT field AS new_field FROM table WHERE ...;
If it runs ok, copy it
Go to VIEW and do that: CREATE OR REPLACE VIEW new_view AS <QUERY>;
Save the view and use it as table.
enjoy.
In my way, you can do alias for the field and create view to store it. which ll act like table.
select subj, user as new from table_name;
By using the above query can get subj and new as a field.
And create view.
create or replace view_name as
select subj, user as new from table_name;
And just call
select view_name;

Resources