Afternoon all!
I'm working on a large database at work, and they've specifically asked me to implement triggers into the database.
Basically, we have a set of tables all containing different information, but if, in one particular table, a certain range of values are entered into the 'fieldID' column, I need it to trigger.
In this case, if a user INSERT data, with the fieldID >= 4 AND fieldID <=9, I need the SQL Server to trigger, with a command of inserting the data to a different table.
For example,
INSERT INTO myTestTable(state, process, fieldID) VALUES ('ACTIVE', 13,9);
(and the database actually performing)
INSERT INTO myFieldTable(state, process, fieldID) VALUES ('ACTIVE', 13,9);
INSERT INTO myTestTable(state, process, fieldID) VALUES ('ACTIVE', 13,42);
(and the database actually performing)
INSERT INTO myTestTable(state, process, fieldID) VALUES ('ACTIVE', 13,42);
I've found loads of stuff online about triggers and how they work in when a new record is entered in general, but nothing for specific data
In the simplest form, you can write a INSTEAD OF INSERT trigger to achieve what you are trying. something like below
CREATE TRIGGER trg_testoninsert on myTestTable
INSTEAD OF INSERT
AS
BEGIN
IF inserted.fieldID >= 4 AND inserted.fieldID <=9
INSERT INTO myFieldTable(state, process, fieldID)
select state, process, fieldID
from inserted;
END;
GO
Related
I have the below changeset but, I may want to add additional inserts in the future. It could be in the hundreds or thousands.
--changeset author:changesetid endDelimiter:;
INSERT INTO "MY_TABLE" (id, name) VALUES (1, 'bob');
INSERT INTO "MY_TABLE" (id, name) VALUES (2, 'jim');
INSERT INTO "MY_TABLE" (id, name) VALUES (3, 'mick');
I can't execute previous inserts because that would throw errors about that data already existing. Similarly, I don't want to have dozens or hundreds of individual changesets with their own combination of different inserts overtime. I would like everything consolidated under 1 changeset.
Maybe I could use some type of precondition with this attribute but, I wouldn't want to keep checking the table size (or have to update the precondition value) everytime I need to update the changeset.
--preconditions onFail:WARN
How about:
create 2 changesets
1st
-insert your data to e.g MY_TABLE_TMP ( table without PK allowing duplicates)
add TRUNCATE at the beginning of this changeset and new inserts below,
2st
your final changeset (sql script)
use a LOOP to get data from MY_TABLE_TMP and insert it with dynamic SQL into
MY_TABLE
when error occures, ignore it and continue a LOOP
RafaĆ
Does your target database support an UPSERT or MERGE statement? If so, you could make your SQL script so if the record is already found in the table nothing happens, and if not found the record is inserted. This would make your script more complicated, but should achieve what you are looking for if you set the changeset to runOnChange.
How would I insert into multiple tables with one sql script in db2
For example, insert a row into T1 DOCK_DOOR and then insert into T2 DOCK_DOOR_LANE multiple times based on the dock_door_sysid from the first table.
My first approach was the following. I was attempting to use a with with three inserts. on the other hand, doing to inserts on the second table is not and option if this can be automated with one insert.
thanks for any feedback
sql example
WITH ins AS (
INSERT INTO DBF1.DOCK_DOOR (DOCK_DOOR_SYSID,DOOR_NUMBER,DOOR_NAME,DOCK_SYSID,DOOR_SEQ,ENCRYPTION_CODE,RFID_ENBLD_FLAG,LANES_COUNT,CMNT_TEXT,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER,ACTIVE_FLAG,STATUS_SYSID,DOOR_TYPE_SYSID)
VALUES (nextval for DBF1.DOCK_DOOR_SEQ,'026','DOOR025',61,25,NULL,'N','2',NULL,current timestamp,'SQL_INSERT',current timestamp,'SQL_INSERT',0,NULL,1723,1142)
RETURNING door_number,dock_door_sysid),
ins2 AS (
INSERT INTO SIT.DOCK_DOOR_lane (DOCK_DOOR_LANE_SYSID,DOOR_LANE_ID,DOCK_DOOR_SYSID,LANE_ID,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER)
VALUES (nextval for DBF1.DOCK_DOOR_LANE_seq,door_number||''||'A',dock_door_sysid,'A',current timestamp},'SQL_INSERT',current timestamp,'SQL_INSERT',0)
SELECT door_number,dock_door_sysid FROM DBF1.DOCK_DOOR
RETURNING door_number,dock_door_sysid)
INSERT INTO DBF1.DOCK_DOOR_lane (DOCK_DOOR_LANE_SYSID,DOOR_LANE_ID,DOCK_DOOR_SYSID,LANE_ID,CREATE_TS,CREATE_USERID,UPDATE_TS,UPDATE_USERID,VER_NUMBER)
VALUES (nextval for DBF1.DOCK_DOOR_LANE_seq,door_number||''||'B',dock_door_sysid,'B',current timestamp},'SQL_INSERT',current timestamp,'SQL_INSERT',0)
SELECT door_number,dock_door_sysid FROM DBF1.DOCK_DOOR;
Table 1 = dock_door
Table 2 = Dock_door_lane
You could do it with a trigger on the dock_door table.
However, if you're on a recent, version on IBM i. You might be able to make use of data change table reference
Your statement would look something like this
insert into dock_door_lane
select <....>
from final table (insert into dock_door <...>)
I'm not sure it will work, as this article indicates that at least at a couple of years ago DB2 for i didn't support the secondary insert required.
This old SO question also seems to confirm that at least at v7.1, the double insert isn't supported.
If I get a chance, I'll run a test on a 7.2 system Monday.
Is it possible to populate a second table when I insert into the first table?
Insert post to table1 -> table 2 column recieves table1 post's unique id.
What I got so far, am I on the right track?
CONSTRAINT [FK_dbo.Statistics_dbo.News_News_NewsID] FOREIGN KEY ([News_NewsID]) REFERENCES [dbo].[News] ([NewsID])
Lots of ways:
an insert trigger
read SCOPE_IDENTITY() after the first insert, and use it to do a second
use the output clause to do an insert
Examples:
1:
create trigger Foo_Insert on Foo after insert
as
begin
set nocount on
insert Bar(fooid)
select id from inserted
end
go
insert Foo (Name)
values ('abc');
2:
insert Foo (Name)
values ('abc');
declare #id int = SCOPE_IDENTITY();
insert Bar(fooid)
select #id
3:
insert Bar(fooid)
select id from (
insert Foo (Name)
output inserted.id
values ('abc')) x
The only thing I can think of is that you can use a trigger to accomplish this. There is nothing "built in" to SQL Server that would do it. Why not just do it from your .NET code?
Yes it is, it sounds like you want a SQL Trigger, this would allow you to trigger logic based on actions on one table, to perform other actions in the DB. Here's another article on creating Simple SQL Triggers
SQL Server 2008 - Help writing simple INSERT Trigger
A Word of caution, this will do all the logic of updating the new table, outside of any C# code you write, it might sound nice to not have to manage it upfront, but you also lose control over when and if it happens.
So if you need to do something different later, now you have to update your regular code, as well as the trigger code. This type of logic can definitely grow, in large systems, and become a nightmare to maintain. Consider this, the alternative would be to build a method that adds the id to the new table after it inserts into the first table.
While i don't know what you're using to do your inserts assuming it's a SQL Command you can get back the ID on an identity column from the insert using Scope_Identity, found here
How to insert a record and return the newly created ID using a single SqlCommand?
if it's EF or some other ORM tool, they should either automatically update the entity, or have other mechanisms to deliver this data.
To understand an application it would be quite helpful if every database change could be logged somehow. Then you can execute an action on the frontend and see what happens in the database. (I only care about the last 5 minutes, or so, but more would not hurt.) What possibilities exist for that?
I know it is possible to configure the JDBC driver to log the executed statements, but it logs rather more than I want to see (I don't care about queries, for instance) and is mixed wildly into your logfiles. :-/
Another thing I can think of is to create triggers for each table that write data on the changes into a logging-table. Did anyone manage to do that? Especially creating a script that creates those triggers for a given set of tables?
You can find many examples of triggers in Oracle documentation. What you need is after insert, update, delete for each row triggers to populate your log tables. Here's some example from Oracle docs:
http://docs.oracle.com/cd/B28359_01/appdev.111/b28370/triggers.htm#LNPLS020
CREATE TABLE Emp_log (
Emp_id NUMBER,
Log_date DATE,
New_salary NUMBER,
Action VARCHAR2(20));
CREATE OR REPLACE TRIGGER Log_salary_increase_ARUID
AFTER UPDATE OR INSERT OR DELETE ON emp
FOR EACH ROW
BEGIN
-- Can be separated for Inserting then Updating with addl if
-- In this case it may be easier to control and/or add flags to your log tables
-- such as Action = 'INS' or Action = 'UPD' --
If (INSERTING OR UPDATING)
THEN
-- Insert newly created/updated values to your log table --
INSERT INTO Emp_log (Emp_id, Log_date, New_salary, Action)
VALUES (:NEW.Empno, SYSDATE, :NEW.SAL, 'INS_UPD');
ELSE
-- Deleting - insert old or deleted values to your logs --
INSERT INTO Emp_log (Emp_id, Log_date, New_salary, Action)
VALUES (:OLD.Empno, SYSDATE, :OLD.SAL, 'DEL');
END;
/
With the triggers you can just keep the previous data (a history of your data). why you don't simply insert your logs in a log table?
hi i have a problem to insert data in multiple tables. i have define primary key & reference key in tables now i want to insert data in both tables in single query.......how can i do this...........???????
Your question isn't exactly clear on what the particular problem is. I can see three possibilities:
1. You want to insert into two tables wiht a single INSERT statement
2. You want to do two inserts, but without anything else being able to 'get in the middle'
3. You want to insert into one table, then get the primary key to insert into the second table
The answer to 1. is simple:
You can't.
The answer to 2. is simple too:
BEGIN TRANSACTION
INSERT INTO <table1> (a,b,c) VALUES (1,2,3)
INSERT INTO <table2> (a,b,c) VALUES (1,2,3)
COMMIT TRANSACTION
The answer to 3. is has several possibilities. Each depending on exactly what you want to do. Most likely you want to use SCOPE_IDENTITY() but you may also want to look up ##identity and IDENT_CURRENT() to understand the various different options and complexities.
BEGIN TRANSACTION
INSERT INTO <dimension_table> (name)
VALUES ('my new item')
INSERT INTO <fact_table> (item_id, iteam_value)
VALUES (SCOPE_IDENTITY(), 1)
COMMIT TRANSACTION
This is what transactions are meant for. Standard SQL does not permit a single statement inserting into multiple tables at once. The correct way to do it is:
-- begin transaction
insert into table 1 ...
insert into table 2 ...
commit
Does your language support the INSERT ALL construct? If so, that is the best way to do this. In fact it's the only way. I posted an example of this construct in another SO thread (that example syntax comes from Oracle SQL).
The other option is to build a transactional stored procedure which inserts a record into the primary key table followed by a record into the referencing table.
And 1 of your choice to do that is use ORM (like Hibernate, NHibernate) the you make your object and set other relation to it and finally just save the main object , like:
A a;
B b;
C c;
a.set(b);
a.set(c);
DAO.saveOrUpdate(a);
you must notice your DAO.saveOrUpdate(a); line of code just work with hibernate but it insert data into 3 table A, B, C.