SQL loop for updating rows - sql-server

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

Related

SQL after update trigger between two tables

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

Use of inserted and deleted tables for logging - is my concept sound?

I have a table with a simple identity column primary key. I have written a 'For Update' trigger that, among other things, is supposed to log the changes of certain columns to a log table. Needless to say, this is the first time I've tried this.
Essentially as follows:
Declare Cursor1 Cursor for
select a.*, b.*
from inserted a
inner join deleted b on a.OrderItemId = b.OrderItemId
(where OrderItemId is the actual name of the primary identity key).
I then do the usual open the cursor and go into a fetch next loop. With the columns I want to test, I do:
if Update(Field1)
begin
..... do some logging
end
The columns include varchars, bits, and datetimes. It works, sometimes. The problem is that the log function is writing the a and b values of the field to a log and in some cases, it appears that the before and after values are identical.
I have 2 questions:
Am I using the Update function correctly?
Am I accessing the before and after values correctly?
Is there a better way?
If you are using SQL Server 2016 or higher, I would recommend skipping this trigger entirely and instead using system-versioned temporal tables.
Not only will it eliminate the need for (and performance issues around) the trigger, it'll be easier to query the historical data.

Update SQL Table Based On Composite Primary Key

I have an ETL process (CSV to SQL database) that runs daily, but the data in the source sometimes changes, so I want to have it run again the next day with an updated file.
How do I write a SQL statement to find all the differences?
For example, let's say Table_1 has a composite PRIMARY KEY consisting of FK_1, FK_2 and FK_3.
Do I do this in SQL or in the ETL process?
Thanks.
Edit
I realize now this question is too broad. Disregard.
You can use EXCEPT to find which are the IDs which are missing. For example:
SELECT FK_1, FK_2, FK_2
FROM new_data_table
EXCEPT
SELECT FK_1, FK_2, FK_2
FROM current_data_table;
It will be better (in performance prospective) to materialized these IDs and then to join this new table to the new_data_table in order to insert all of the columns.
If you need to do this in one query, you can use simple LEFT JOIN. For example:
INSERT INTO current_data_table
SELECT A.*
FROM new_data_table A
LEFT JOIN current_data_table B
ON A.FK_1 = B.FK_1
AND A.FK_2 = B.FK_2
AND A.FK_3 = B.FK_3
WHRE B.[FK_1] IS NULL;
The idea is to get all records in the new_data_table for which, there is no match in the current_data_table table (WHRE B.[FK_1] IS NULL).

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.

Populating a table with fields from two other tables

I have two tables in Filemaker:
tableA (which includes fields idA (e.g. a123), date, price) and
tableB (which includes fields idB (e.g. b123), date, price).
How can I create a new table, tableC, with field id, populated with both idA and idB, (with the other fields being used for calculations on the combined data of both tables)?
The only way is to script it (for repeating uses) or do it 'manually', if this is an ad-hoc process. Details depend on the situation, so please clarify.
Update: Sorry, I actually forgot about the question. I assume the ID fields do not overlap even across tables and you do not need to add the same record more than once, but update it instead. In such a case the simplest script would be like that:
Set Variable[ $self, Get( FileName ) ]
Import Records[ $self, Table A -> Table C, sync on ID, update and add new ]
Import Records[ $self, Table B -> Table C, sync on ID, update and add new ]
The Import Records step is managed via rather elaborate dialog, but the idea is that you import from the same file (you can just type file:<YourFileName> there), the format is FileMaker Pro, and then set the field mapping. Make sure to choose the Update matching records and Add remaining records options and select the ID fields as key files to sync by.
It would be a FileMaker script. It could be run as a script trigger, but then it's not going to be seamless to the user. Your best bet is to create the tables, then just run the script as needed (manually) to build Table C. If you have FileMaker Server, you could schedule this script to be run periodically to keep Table C up-to-date.
Maybe you can use the select into statement.
I'm unsure if you wish to use calculated field from TableA and TableB or if your intension was to only calculate fields from the same table?
If tableA.IdA exists also in tableB.IdA, you could join the two tables and select into.
Else, you run the statement once for each table.
Select into statement
Select tableA.IdA, tableA.field1A, tableA.field2A, tableA.field1A * tableB.field2A
into New_Table from tableA
Edit: missed the part where you mentioned FileMaker.
But maybe you could script this on the db and just drop the table.

Resources