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?
Related
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.
I have a query like this:
Select table1.*, table2.column1 from table1 join table2 on table1.column1=table2.column1
It works, but it puts the column in the end of the datagridview, but i have to put table2.column1, after a specified column of table2, and i have to use table1.* and i cant use listing of the table1's columns is it possible?
And why exactly can't you use a list of all the fields?
NO , it's not possible to place a column in the middle of columns specified with * , not with pure SQL and not with dynamic.
Just specify them, don't be lazy, it's better practice:
SELECT table1.col1,
table1.col2,
table2.col1,
table1.col3
..........
because i am using union queries, and the table names are changing and one table contains more colums than the other
if table1 differs, that above all should be a strong argument for specifing all needed fields separatly. In case of a new field in table1, your query would be broken, cause the number of fields will differ from the ones used in the next union.
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
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),
....
);"
Is is possible to get new values for Id (IDENTITY) before inserting data in a table ?
Is is possible to write something like that :
INSERT INTO Table1
SELECT *GET_NEW_IDENTITY*, Field1, Field2 FROM Table2
I need the values of Id because I want to insert data in Table1 and, just after, insert data in another table which has a foreign key linked to Table1 (with Id)
IDENT_CURRENT. Returns the last identity value generated for a specified table or view. The last identity value generated can be for any session and any scope.
SCOPE_IDENTITY. Returns the last identity value inserted into an identity column in the same scope. A scope is a module: a stored procedure, trigger, function, or batch.
OUTPUT. Returns information from, or expressions based on, each row affected by an INSERT, UPDATE, DELETE, or MERGE statement. [...] The OUTPUT clause may be useful to retrieve the value of identity or computed columns after an INSERT or UPDATE operation.
you can also have the insert statement return the newly inserted value for later use. for example
create table demo( Id int identity primary key, data varchar(10))
go
insert into demo(data) output inserted.Id values('something')
No, because it is the act of adding a row which creates the new identity value.
To do what you want,
SELECT newid = ##identity FROM table
just after the INSERT
Why would you need to get the identity value before doing the insert? Just do the insert to Table2 returning SCOPE_IDENTITY() and then use the resulting Id value for your insert to Table1.
This is just fast demo. You can use new ID for insert for update, insert into another table, query, etc. in another way. Hoping I did not insert errors into script during formatting, editing post
-- run [1] before this script once to have environment
--create temporary table once if not dropped after
-- really only ID field is needed, the others are for illustration
create table #temp_id (Id int, d1 int, d2 int)
select * from Table2;-- this is read-only, filled once here source
select * from Table1;--interesting for following runs
insert into Table1
OUTPUT INSERTED.id
-- really only ID is needed, the rest is for illustration
, inserted.d1, inserted.d2 INTO #temp_id
select field1, field2, null-- null to be merged later
-- or inserted/updated into another table
from Table2;
select * from Table1;
select * from #temp_id;
MERGE Table1 AS TARGET
USING #temp_id AS SOURCE
ON (TARGET.id = SOURCE.id)
WHEN MATCHED
--AND OR are redundant if Table1.ID is PK
THEN
UPDATE SET TARGET.IDnew = SOURCE.id;
select * from Table1;
--drop table #temp_id
--drop table table1
--drop table table2
[1]
Reproducing the tables from question and filling with data
create table Table1( Id int identity primary key, d1 int, d2 int, IDnew int)
create table Table2( field1 int, field2 int)
insert into table2 values(111,222)
insert into table2 values(333,444)
IDENT_CURRENT('tableName') returns the current value of the identity for the given table. The identity value that will be assigned on Insert will be IDENT_CURRENT('tableName') + IDENT_INCR('tableName').
SELECT IDENT_CURRENT('tableName') + IDENT_INCR('tableName')