SQLite In Clause not working in trigger - c#

i have two tables Table1 and Table2. Table1 have columns ID,stringIDs and Table2 Columns ID,data
i have created a trigger to delete rows based on table1.
it doesn't works if comma Seperated stringIDs
are more than one. it works if stringIDs is only single value
create trigger tgTriggerName after delete
on Table1
begin
delete from Table2 where ID in (old.stringIDs);
end

Gordon is right, this table structure is really probably not what you want. But if for some reason you must do it this way, this query might accomplish what you want:
delete from Table2
where ID = old.stringIDs -- ID matches exactly
or old.stringIDs like ID + ',%' -- Or ID is at beginning of list
or old.stringIDs like '%,' + ID -- Or ID is at end of list
or old.stringIDs like '%,' + ID + ',%' -- Or ID is in middle of list
But that's a mess. Don't do it. Instead remove the stringIDs column from Table1, and add a column to Table2 called Table1ID to indicate which Table1 ID this Table2 record belongs to. So Table2 would look like this
ID Table1ID Data
1 1 some data
2 1 some data
3 2 some data
4 2 some data
5 2 some data
...
Then your trigger query can simply be:
delete from Table2
where Table1ID = old.ID
Even more clean would be to skip the trigger completely and do a Foreign Key Contstraint with cascading delete. But I have a feeling that's a lesson for another day.

'stringIDs' from table1 save them in another table with foreign key reference than apply trigger on new table to delete records from table 2

Related

compare rows and update if different values and insert if doesn't exist

I have a TABLE1 and TABLE2 with same columns(around 15) except TABLE2 has additional date fields. I am trying to loop through TABLE1(around 25,000) rows and insert into TABLE2 if row doesn't exist.
This can be done without any issues but I would like to update TABLE2 only if any column value is different from TABLE1. Do I have to check manually compare each column value and update? I couldn't find any easier ways to do this. The reason I would like to do this because I want to insert a row into a History table only when there is any update or insert.
begin
update table set ...
where key = #key
end
else
begin
insert into table (key, ...)
values (#key, ...)
end
+1 for recommending MERGE because that is a correct method that can handle both instances in a single statement. If you are not familiar with it, you can run two separate statements (UPDATE/INSERT).
For UPDATING:
If you want to update based on any column not being equal based on whatever key you have joined to is fairly simple. You can get a list of all columns from either table (easiest is to right click the table and SELECT TOP 1000).
Highlight the columns and press Shift + Tab and remove all commas with a CTRL + F, Replace All. Copy and Paste that into Excel, column A.
Insert the following formula in column B:
B1: ="T1."&A1&" <> T2."&A1&","
B2: ="OR T1."&A2&" = T2."&A2&","
Copy and paste the formula in B2 all the way down the list. So:
UPDATE T1
SET T1.Column1 = T2.Column1
,T1.Column2 = T2.Column2
,T1.Column3 = T2.Column3
,T1.Column4 = T2.Column4
FROM Table1 T1
INNER JOIN Table2 T2
ON T1.Table1PrimaryKey = T2.Table2PrimaryKey
WHERE T1.Column1 <> T2.Column1
OR T1.Column2 <> T2.Column2
OR T1.Column3 <> T2.Column3
OR T1.Column4 <> T2.Column4
Note: Since all columns being compared are being updated if any column combination doesn't match then you are fine because updating a column that matches will not hurt anything. And, if you are implementing a slowly changing dimension where you track the date change then the updated date is still valid because at least one column record did not match and was thus updated.
For INSERTING:
INSERT INTO Table1 (Column1, Column2, Column3, Column4)
SELECT T2.Column1
,T2.Column2
,T2.Column3
,T2.Column4
FROM Table2 T2
WHERE T2.Table2PrimaryKey NOT EXISTS (SELECT T1.Table1PrimaryKey FROM Table1 T1)
ORDER BY T2.Table2PrimaryKey
Note: The above INSERT assumes that your PrimaryKey column is an IDENTITY column, which cannot be INSERTED on because it is auto calculated. In the event that you are using a primary key that is not an IDENTITY field then you will need to include it into the INSERT clause. Also, the ORDER BY will INSERT the records in order of the PRIMARY KEY. This is useful when the PRIMARY KEY is an IDENTITY field because the calculated value will at least be in order of where it came from. In the event that all INSERTS use this methodology AND the destination table receives records only from the receiving table AND there have been neither any RESEEDS nor deletions, then the IDENTITY Primary key column value will be identical.
You would need to do it column at a time
If you have some null you need to do checks for that
insert into history
select t1.id, t1.col1, t2.col1
from table2 t2
join table1 t1
on t2.id = t1.id
and t1.col1 <> t2.col
update t2
set t2.col1 = t1.col1
from table2 t2
join table1 t1
on t2.id = t1.id
and t1.col1 <> t2.col
You could also just do the update with an ouput clause
For the insert use not exists
Assuming that this is something you need to do more than once, I would suggest you use an insert and an update trigger on table A, that keeps table B up to date.

Compare 2 big tables (SQL Server) [duplicate]

This question already has answers here:
SQL how to compare two tables for same data content?
(21 answers)
Closed 6 years ago.
I have 2 big tables(About 100-150k rows in each).
The structure of these tables is the same. Ids of entities are also the same in each table.
I need a very fast way to compare these tables and answer the following questions:
Which row's fields are different from another table's row?
Which ids exists in first table and doesn't exists in second table?
Which ids exists in second table and doesn't exists in first table?
Thank you!
Edit: I need to do this comparison using C# or maybe stored procedures(and then to select results by c#)
If you have two tables Table1 and Table2 and they have the same structure and primary key named ID you can use this SQL:
--Find rows that exist in both Table1 and Table2
SELECT *
FROM Table1
WHERE EXISTS (SELECT 0 FROM Table2 WHERE Table1.ID = Table2.ID)
--Find rows that exist in Table1 but not Table2
SELECT *
FROM Table1
WHERE NOT EXISTS (SELECT 0 FROM Table2 WHERE Table1.ID = Table2.ID)
If you are trying to compare and find rows that differ in one column or another, that is a little trickier. You can write SQL to check each and every column yourself, but it may be simpler to add a temporary CHECKSUM column to both tables and compare those. If the checksums are different then one or more columns are different.
SQL Data Compare is a great tool for doing this. Also Microsoft Visual Studio SQL Server Data Tools has a Data Compare function.
I found the following method to perform very well when comparing large data sets.
http://weblogs.sqlteam.com/jeffs/archive/2004/11/10/2737.aspx
Basically UNION ALL of the two data sources then aggregate them and return only rows which don't have an identical matching row in the other table.
With unionCTE As (
Select 'TableA' As TableName, col1, col2
From TableA
Union All
Select 'TableB', col1, col2
From TableB)
Select Max(TableName), col1, col2
From unionCTE
Group By col1, col2
Having Count(*) = 1
Order By col1, col2, TableName;
This will show the results in a single resultset, and if there are any rows that have the same key but different values the rows will be one above the other so that you can easily compare which values have changed between the tables.
This can easily be put into a stored procedure, if you want.

SqlBulkCopy many-to-many table

I am wondering if there is any possibility to get last inserted ID in SqlBulkCopy?
Table 1 Table2 Many-To-Many-Table
attribute attribute Table1.id, Table2.id
I have middle table for many to Manyrelationship So I need to get last insertd Id from table1 and table2, and then I need to insert both of them in Many-To-Many-Table.
Is that possible?

SQL UPDATE CLASS_NUMBER BY NAME ORDER

I dont know if i choose the right title for my question.
I have that table like this in my database.
NAME class_num
-------------------------------------------------- --------
name1 2
name2 4
name3 1
And what I want to do is:
Update the class_num to be in order like the name. The result from what I want is that:
NAME class_num
-------------------------------------------------- ---------
name1 1
name2 2
name3 3
Is any way to do that with a QUERY?
Or I need to do from C# code?
Sorry my english, please help. Thanks.
In SQL Server, you can use an updatable CTE (or subquery):
with toupdate as (
select t.*, row_number() over (order by name) as new_class_num
from table t
)
update toupdate
set class_num = new_class_num;
Assuming:
that your ID field is not an IDENTITY field, and can be updated
That your Name column holds unique values (there are no duplicate names)
You can do something like this (example in T-SQL for SQL Server):
-- Select all Names in alphabetical order, and give them a row number
INSERT INTO #NewIdTable
SELECT ROW_NUMBER() OVER(ORDER BY name ASC) as Row, Name
FROM MyTable
-- Update the ID's using the RowNumber as a new ID.
UPDATE MyTable
SET Id = Row
FROM #NewIdTable INNER JOIN MyTable ON #NewIdTable.Name = MyTable.Name
Edit: Looks like you clarified in the comments that your class_num column is a key. Therefore you will have to adjust this method. Try updating "Name" by joining on the row-number instead, if your ID's are sequential. Alternately, you could drop the key constraint temporarily, update the ID's, and create the key again. Another method might be to simply create a new table with IDENTITY INSERT ON and copy the names over to it in alphabetical order.
Firstly You can delete your table that query
"TRUNCATE TABLE table_name"
And later, you can create your table again with that query
"CREATE TABLE table_name
(
column_name1 data_type(size),
column_name2 data_type(size),
column_name3 data_type(size),
....
);"

How to get the newly added records

In my application, i want to show the newly added RECORDS by an import operation in a gridview. Is there is any method in sql to retrive newly added rows.
I tried to do it in using code and tried to get the difference before and after the insertion and its working perfectly but makes the application very slow. So, i want to do it in database itself.
Im using Mysql, ASP.NET.
Eg:
table may have these records before the import operation
ID Name
1 A
2 B
3 C
and after import the table may be like this.
ID Name
1 A
2 B
3 C
4 D
5 E
6 F
I want result like
ID Name
4 D
5 E
6 F
You need to have AUTO_INCREMENT column defined on table or alternatively you can use TIMESTAMP field to retrieve newly added records, try this:
SELECT *
FROM table_name
ORDER BY id DESC
LIMIT 10;
For single row insert you can use LAST_INSERT_ID after you INSERT query:
SELECT LAST_INSERT_ID();
For multi-row insert you can follow these steps:
START TRANSACTION;
SELECT MAX(id) INTO #var_max_id FROM table_name;
INSERT INTO table_name VALUES(..),(..),...;
SELECT MAX(id) INTO #var_max_id_new FROM table_name;
COMMIT;
SELECT *
FROM table_name
WHERE id BETWEEN (#var_max_id + 1) AND #var_max_id_new;
i think this will be more simple:
SELECT MAX(id) INTO #Max_table_Id FROM table;
// Insert operation here//////
SELECT * FROM table WHERE id>#Max_table_Id;
In case you use auto incremental IDs for your records, you can use:
SELECT * FROM [table] ORDER BY [id column] DESC LIMIT [number of records]
Otherwise you should add a TIMESTAMP colum to your records for this purpose and select by this column.
Personally, if there is an option, I wouldn't use the record IDs for this, as it is not what they are for. Record IDs can change throughout the lifetime of an application and they don't necessarily represent the order in which the items were added. Especially in data import/export scenarios. I'd prefer to create special columns to store such information, e.g. "CreatedAt", "ModifiedAt".

Categories