SQL after update trigger between two tables - sql-server

I have two tables, Engineering and Electrical. Work is done in the Engineering table, then the Electrical team starts work after that. They share some of the same columns. Those columns are
Tag
Service Description
Horsepower
RPM
Project Number
I want to create an after update trigger so that when the Tag column gets filled in the Electrical table and that data matches the data in one of the Tag columns in the Engineering table, the other four same columns in the Engineering table automatically are sent to the corresponding columns in the Electrical table.
Below is what I tried which obviously doesn't work:
CREATE TRIGGER [dbo].[tr_Electrial_Update]
ON [dbo].[ENGINEERING]
AFTER UPDATE
AS
BEGIN
INSERT INTO ELECTRICAL ([ICM_SERVICE_DESCRIPTION_],[PROJECT_NUMBER_], [ICM_POWER_HP_], [ICM_POWER_KW_], [ICM_RPM_])
SELECT
i.[ICM_SERVICE_DESCRIPTION_], i.[PROJECT_NUMBER_],
i.[ICM_POWER_HP_], i.[ICM_POWER_KW_], i.[ICM_RPM_]
FROM
ENGINEERING m
JOIN
inserted i ON i.[TAG_] = m.[TAG_]
END
I'm someone trying to teach myself SQL on the fly so be kind. As always I'm very appreciative of any help.

From your post, I'm assuming you already have an entry in the Electrical table, and it's column Tag gets updated from NULL to some other value. This syntax is for SQL Server - you didn't explicitly specify what RDBMS you're using, but it looks like SQL Server to me. If it's not - adapt as needed.
Assuming you have only a single row in Engineering that matches that Tag value, you can do something like this - it has to be an UPDATE statement since you already have a row in Electrical - you want to update some columns, not insert a completely new row:
CREATE TRIGGER [dbo].[tr_Electrical_Update]
ON [dbo].Electrical
AFTER UPDATE
AS
BEGIN
IF UPDATE(Tag)
UPDATE dbo.Electrical
SET [ICM_SERVICE_DESCRIPTION_] = eng.[ICM_SERVICE_DESCRIPTION_],
[PROJECT_NUMBER_] = eng.[PROJECT_NUMBER_],
[ICM_POWER_HP_] = eng.[ICM_POWER_HP_],
[ICM_POWER_KW_] = eng.[ICM_POWER_KW_],
[ICM_RPM_] = eng.[ICM_RPM_]
FROM Inserted i
INNER JOIN dbo.Engineering eng ON i.Tag = eng.Tag
WHERE Electrical.Tag = i.Tag;
END

Related

SQL loop for updating rows

I'm new to SQL Server. The scenario is the following:
I have a csv with a bunch of Serial N0, which are unique.
Example:
Serial No
-----------
01561
21654
156416
89489
I also have a SQL Server database table, where are several rows which can be identified with the serial no. For example I have 6 rows in the SQL Server table with the serial no. 01561. Now I want to update a field in all these rows with "Yes". If it is only about this number, I know the solution it's
UPDATE dbo.Table1
SET DeleteFlag = 'Yes'
WHERE Serial No. = 01561;
Unfortunately I have more than 10,000 Serial No in the csv for what I have to do that. Can you help me to find a solution for that?
First you should use the TASK feature to import the CSV. You right click to do this on the database and select "TASK" and import data. Its a UI which is pretty self explanatory, so itll help you get the job done quickly and easily. Make note of the name you give the table, SQL Server will try and give it a defualt name with a "$" in the name. Change that to something like "MyTableImport". If the data is already in SQL Server, go to the next step.
Step 2 - You can do the UPDATE for the entire table via a join. All youre doing is matching the ID's to another table, right? Looping would be a bad idea here especially since itll take a minute to loop through 10000+ and run an update FOR EACH ONE. Thats against an idea known as "Set based approach" which to sum it up nicely is to do things all at once (google it though because im horribly over simplifying the idea for you). Here is a sample update join query for you:
UPDATE x
SET x.DeleteFlag='Yes'
FROM yourimportable y
INNER JOIN yourLocal x ON y.SerialNo=x.SerialNo
Assuming that you have created a temp table to load CSV with a bunch of serial number. Now you can update your permanent table with the temp table data using update join like this:
UPDATE t1
SET t1.DeleteFlag = 'Yes'
FROM dbo.Table1 AS t1
INNER JOIN #TempTable2 AS t2
ON t1.Serial_No = t2.Serial_No

Updating one column in Oracle

I have an Oracle table which contains a column called dt_code, first_name, last_name, and user_id. I need to update dt_code with a list of codes that was given to me in an excel file. What would be the best way to update the column and maintain the relationships.
as simple as
update your_table
set dt_code = new_code
where id = specific_id;
this won't break any relationships.
Note that Oracle allow you to import xls datas, but since I have no idea of your syntax it is hard to tell you how to do it.
If there is a lot of update to do, you should import all the datas in a temporary table, then do the update based on this table.
If you choose this option and you are not used to this kind of update statement, have a look at this thread Update statement with inner join on Oracle.

SQL server : Inserting/updating missing data from one table to another

I have two table "Container" and "Control". These are existing tables and there is no foreign key relationship between the two. These are also very old tables so are not normalized. And I cannot change the structure now.
Below is the structure of the two tables.
Container table :
Control Table :
The Name field in Control table contains CTableName+CPName from Container table.
I want to update the columnName field of Control table with the value of CID column of Container table. and also want to insert one more record (for ctable2 i.e the fourth row in final Control table below) in Control table.
The tablename and columnname columns have will always be have default values.
The final Control table should look like this:
How do I do this?
I hope you want to apply this fix because you want normalize your table structure.
Try this:
First step:
In this way you'll UPDATE all Control rows with the value of Container table where the couple fields CTableName and CPName are the same of Name (excluding the rows of Container with the same couple fields)
UPDATE Control
SET ColumnValue = (
SELECT c.CID
FROM Container c
WHERE c.CTableName + '+' + c.CPName = Control.Name
AND NOT EXISTS(
SELECT 'PREVIOUS'
FROM Container c2
WHERE c.CTableName = c2.CTableName
AND c.CPName = c2.CPName
AND c.CID < c2.CID
)
),
TableName = 'default', ColumnName = 'default'
WHERE ColumnValue IS NULL
Second step:
Adding elements don't present in Control table
INSERT INTO Control (field list)
SELECT field list
FROM Container co
WHERE NOT EXISTS(
SELECT 'in_control'
FROM Control ct
WHERE co.CID = ct.ColumnValue
)
After these two steps you can drop column Name in Control table
I am an Oracle plsql programmer and worked with Sql-server as well.
First you should describe the relationship between the 2 tables, in the end i could figger it out but it's better you explain it yourself.
To update a table with information from another table you should ask yourself:
- when should the update take place?
- what are the conditions to start the update?
- how should the update be done?
In Oracle there is a database object called a trigger. It's quite a handy object and probably just what you need. I believe that sql-server has it too.
Pls fee free to ask any questions but do read the sql-server appropriate manual as well.
Good luck, Edward.

Merge query using two tables in SQL server 2012

I am very new to SQL and SQL server, would appreciate any help with the following problem.
I am trying to update a share price table with new prices.
The table has three columns: share code, date, price.
The share code + date = PK
As you can imagine, if you have thousands of share codes and 10 years' data for each, the table can get very big. So I have created a separate table called a share ID table, and use a share ID instead in the first table (I was reliably informed this would speed up the query, as searching by integer is faster than string).
So, to summarise, I have two tables as follows:
Table 1 = Share_code_ID (int), Date, Price
Table 2 = Share_code_ID (int), Share_name (string)
So let's say I want to update the table/s with today's price for share ZZZ. I need to:
Look for the Share_code_ID corresponding to 'ZZZ' in table 2
If it is found, update table 1 with the new price for that date, using the Share_code_ID I just found
If the Share_code_ID is not found, update both tables
Let's ignore for now how the Share_code_ID is generated for a new code, I'll worry about that later.
I'm trying to use a merge query loosely based on the following structure, but have no idea what I am doing:
MERGE INTO [Table 1]
USING (VALUES (1,23-May-2013,1000)) AS SOURCE (Share_code_ID,Date,Price)
{ SEEMS LIKE THERE SHOULD BE AN INNER JOIN HERE OR SOMETHING }
ON Table 2 = 'ZZZ'
WHEN MATCHED THEN UPDATE SET Table 1.Price = 1000
WHEN NOT MATCHED THEN INSERT { TO BOTH TABLES }
Any help would be appreciated.
http://msdn.microsoft.com/library/bb510625(v=sql.100).aspx
You use Table1 for target table and Table2 for source table
You want to do action, when given ID is not found in Table2 - in the source table
In the documentation, that you had read already, that corresponds to the clause
WHEN NOT MATCHED BY SOURCE ... THEN <merge_matched>
and the latter corresponds to
<merge_matched>::=
{ UPDATE SET <set_clause> | DELETE }
Ergo, you cannot insert into source-table there.
You could use triggers for auto-insertion, when you insert something in Table1, but that will not be able to insert proper Shared_Name - trigger just won't know it.
So you have two options i guess.
1) make T-SQL code block - look for Stored Procedures. I think there also is a construct to execute anonymous code block in MS SQ, like EXECUTE BLOCK command in Firebird SQL Server, but i don't know it for sure.
2) create updatable SQL VIEW, joining Table1 and Table2 to show last most current date, so that when you insert a row in this view the view's on-insert trigger would actually insert rows to both tables. And when you would update the data in the view, the on-update trigger would modify the data.

How to make tasks double-checked (the way how to store it in the DB)?

I have a DB that stores different types of tasks and more items in different tables.
In many of these tables (that their structure is different) I need a way to do it that the item has to be double-checked, meaning that the item can't be 'saved' (I mean of course it will be saved) before someone else goes in the program and confirms it.
What should be the right way to say which item is confirmed:
Each of these tables should have a column "IsConfirmed", then when that guy wants to confirm all the stuff, the program walks thru all the tables and creates a list of the items that are not checked.
There should be a third table that holds the table name and Id of that row that has to be confirmed.
I hope you have a better idea than the two uglies above.
Is the double-confirmed status something that happens exactly once for an entity? Or can it be rejected and need to go through confirmation again? In the latter case, do you need to keep all of this history? Do you need to keep track of who confirmed each time (e.g. so you don't have the same person performing both confirmations)?
The simple case:
ALTER TABLE dbo.Table ADD ConfirmCount TINYINT NOT NULL DEFAULT 0;
ALTER TABLE dbo.Table ADD Processed BIT NOT NULL DEFAULT 0;
When the first confirmation:
UPDATE dbo.Table SET ConfirmCount = 1 WHERE PK = <PK> AND ConfirmCount = 0;
On second confirmation:
UPDATE dbo.Table SET ConfirmCount = 2 WHERE PK = <PK> AND ConfirmCount = 1;
When rejected:
UPDATE dbo.Table SET ConfirmCount = 0 WHERE PK = <PK>;
Now obviously your background job can only treat rows where Processed = 0 and ConfirmCount = 2. Then when it has processed that row:
UPDATE dbo.Table SET Processed = 1 WHERE PK = <PK>;
If you have a more complex scenario than this, please provide more details, including the goals of the double-confirm process.
Consider adding a new table to hold the records to be confirmed (e.g. TasksToBeConfirmed). Once the records are confirmed, move those records to the permanent table (Tasks).
The disadvantage of adding an "IsConfirmed" column is that virtually every SQL statement that uses the table will have to filter on "IsConfirmed" to prevent getting unconfirmed records. Every time this is missed, a defect is introduced.
In cases where you need confirmed and unconfirmed records, use UNION.
This pattern is a little more work to code and implement, but in my experience, significantly improves performance and reduces defects.

Resources