Get the value of each field that updated in updating operation - c#

i want get value of field after update,
for example i have two table
table1: ID Price UserID type
table2: IDLog ID(FK table1) OldPrice
and i update Price in table 1:
UPDATE table1
SET Price = '1111'
WHERE TYPE = 1
now i want befor every update get value ID table1 and insert into table2,
how i get value every field??

IMHO FOR UPDATE TRIGGER is the way to go. That way you can contain all logging logic inside your DB.

Better way to do it is using trigger on table1 (SQL Server side of course).
CREATE TRIGGER table1_update ON table1 FOR UPDATE
AS
BEGIN
INSERT INTO table2 (IDLog, OldPrice)
SELECT ID, Price
FROM deleted
INNER JOIN inserted ON
deleted.ID = inserted.ID
deleted.Price <> inserted.Price
END

You can use output clause:
update table1
output inserted.ID into table2
set Price='1111' where type=1

You can insert data to table2 before updating.
INSERT INTO table2
SELECT ID, Price from table1
WHERE TYPE = 1
--Update table1 after inserting
UPDATE table1
SET Price = '1111'
WHERE TYPE = 1
Other way to do is to create an update trigger for table1, which inserts the updated data to table2.

Related

Allowing identity insert on temp table produces an error [duplicate]

I created a trigger that performs a check and automatically populates data into 2 tables. Only what happens the following error :
IDENTITY_INSERT is already ON for table 'X'. Cannot perform SET operation for table 'Y'.
I found this while researching the error:
"At any time, only one table in a session can have the IDENTITY_INSERT property set to ON.”
So the fix was easy:
SET IDENTITY_INSERT Table1 ON
-- insert statements for table1
SET IDENTITY_INSERT Table1 OFF
SET IDENTITY_INSERT Table2 ON
-- insert statements for table2
SET IDENTITY_INSERT Table2 OFF
SET IDENTITY_INSERT Table3 ON
-- insert statements for table3
SET IDENTITY_INSERT Table3 OFF
But as the data is populated via trigger is not possible to do so.
Does anyone have a solution to my problem please?
I apologize.
Thank you all.
Trigger-----
CREATE TRIGGER Alert ON registos AFTER INSERT AS
BEGIN
DECLARE #comp decimal = 0
DECLARE #id_sensores_em_alerta decimal
DECLARE #tempmin decimal = 0
DECLARE #current_max_idAlarme int = (SELECT MAX(IdAlarme) FROM alarmes)
DECLARE #maxidAlarme int
DECLARE #temp decimal = (SELECT s.lim_inf_temp from sensores s JOIN inserted i ON s.idSensor=i.idSensor )
-- Insert into alarmes from the inserted rows if temperature less than tempmin
INSERT alarmes (IdAlarme, descricao_alarme,data_criacao, idRegisto)
SELECT
ROW_NUMBER() OVER (ORDER BY i.idRegisto) + #current_max_idAlarme, 'temp Error', GETDATE(), i.idRegisto
FROM
inserted AS i
WHERE
i.Temperatura < #temp
SET #maxidAlarme = (SELECT MAX(IdAlarme) FROM alarmes)
INSERT INTO sensores_tem_alarmes(idSensor,idAlarme,dataAlarme)
SELECT i.idSensor, #maxidAlarme, GETDATE()
FROM inserted i
SET #comp += 1;
SET #id_sensores_em_alerta=1;
SET #id_sensores_em_alerta = (SELECT MAX(id_sensores_em_alerta) FROM sensores_em_alerta)
INSERT INTO sensores_em_alerta(id_sensores_em_alerta, idSensor, idAlarme, data_registo, numerosensoresdisparados)
SELECT #id_sensores_em_alerta, i.idSensor, #maxidAlarme, GETDATE(), #comp
FROM inserted i
end
DataBase----
I had a similar problem but it did not involve table triggers. I was running a script that refreshes data for multiple tables and I hit a foreign key reference error.
According to MSDN:
At any time, only one table in a session can have the IDENTITY_INSERT
property set to ON.
To resolve this, I ran SET IDENTITY_INSERT [dbo].[table_name] OFF for each table I was trying to insert into. Then I was able to refresh my tables again after I corrected the reference error.
Edit: I should also mention that you can just disconnect and then reconnect to reset your session.
Allow SQL Server to insert the identity values automatically for you. Since this is a trigger, there could multiple rows being inserted at a time. For one row inserts, you can use SCOPE_IDENTITY() function (http://msdn.microsoft.com/en-us/library/ms190315.aspx) to retrieve the identity value of your last inserted row. However, since we could have multiple rows inserted in a trigger, we will use the OUTPUT clause (http://msdn.microsoft.com/en-us/library/ms177564.aspx) to get back a list of the inserted IdAlarme values for each idRegisto.
I'm assuming that alarmes.IdAlarme and sensores_em_alerta.id_sensores_em_alerta are the two identity fields in this trigger. If that is the case, then this should work:
CREATE TRIGGER Alert ON registos AFTER INSERT AS
BEGIN
DECLARE #comp decimal = 0
DECLARE #id_sensores_em_alerta decimal
DECLARE #tempmin decimal = 0
DECLARE #temp decimal = (SELECT s.lim_inf_temp from sensores s JOIN inserted i ON s.idSensor=i.idSensor )
DECLARE #tblIdAlarme TABLE (idRegisto int not null, IdAlarme int not null);
-- Insert into alarmes from the inserted rows if temperature less than tempmin
-- IdAlarme is identity field, so allow SQL Server to insert values automatically.
-- The new IdAlarme values are retrieved using the OUTPUT clause http://msdn.microsoft.com/en-us/library/ms177564.aspx
INSERT alarmes (descricao_alarme,data_criacao, idRegisto)
OUTPUT inserted.idRegisto, inserted.IdAlarme INTO #tblIdAlarme(idRegisto, IdAlarme)
SELECT descricao_alarme = 'temp Error', data_criacao = GETDATE(), i.idRegisto
FROM inserted AS i
WHERE i.Temperatura < #temp
;
--It looks like this table needs a PK on both idSensor and idAlarme fields, or else you will get an error here
-- if an alarm already exists for this idSensor.
INSERT INTO sensores_tem_alarmes(idSensor,idAlarme,dataAlarme)
SELECT i.idSensor, a.IdAlarme, dataAlarme = GETDATE()
FROM inserted i
INNER JOIN #tblIdAlarme a ON i.idRegisto = a.idRegisto
;
--not sure what this is doing?? Will always be 1.
SET #comp += 1;
--id_sensores_em_alerta is an identity field, so allow SQL Server to insert values automatically
INSERT INTO sensores_em_alerta(idSensor, idAlarme, data_registo, numerosensoresdisparados)
SELECT i.idSensor, a.IdAlarme, data_registo = GETDATE(), numerosensoresdisparados = #comp
FROM inserted i
INNER JOIN #tblIdAlarme a ON i.idRegisto = a.idRegisto
;
END

TSQL generating update statement for table based on condition

How to generate update statement on the whole table with some condition ? For example I have table
and I would like to specify date (for this example '3/16/2016') and generate something like following Update
UPDATE TableName SET ColumnValue = 30 AND ModifiedDate = '2016-03-17' WHERE Id = 2
If there will be more changes after specified date, I would like to generate all the updates for these changes.
Is there some easy solution or I have to script all this by some customized C# script ?
If you have 2 identical tables and need to update one of the tables based on changes happed after a particular timestamp (#Date) in another table then you can use below query.
UPDATE T1
SET T1.ColumnValue=T2.ColumnValue,T1.ModifiedDate=T2.ModifiedDate
FROM Table1 T1 inner join Table2 T2 on T1.ID=T2.ID
WHERE T2.ModifiedDate>=#Date
If you just want to generate update statements, you could do something like this:
declare #afterDate date = '20160316';
select update_statements = 'update table t set columnvalue = '
+convert(varchar(10),columnvalue)
+', modifieddate = '''
+replace(convert(varchar(10),modifieddate,120),'-','')+''''
+' where id = '+convert(varchar(10),id)+';'
from t
where modifieddate > #afterdate;
rextester demo: http://rextester.com/MZQ68677
returns:
+------------------------------------------------------------------------------+
| update_statements |
+------------------------------------------------------------------------------+
| update table t set columnvalue = 30, modifieddate = '20160317' where id = 2; |
+------------------------------------------------------------------------------+
This gives the trigger to track all the updates for a table. Based on table structure you can add required columns in the tracking table.
CREATE TABLE EMP(ID int, NAME VARCHAR(20), SALARY MONEY)
CREATE TABLE TrackUpdate (Id int identity, updatestmt varchar(500), DateCreated datetime)
GO
INSERT INTO EMP
VALUES
(1, 'A', 10),(2, 'E',40 ),(3,'B',5),(4,'F',40),(5,'I',50)
GO
ALTER TRIGGER TR_EMP ON EMP
INSTEAD OF UPDATE
AS
BEGIN
declare #Name varchar(10)
declare #Salary MONEY
SELECT #Name=Name,#Salary=Salary FROM inserted
insert into TrackUpdate values ('update Emp SET E.Name='''+#Name+''', '+'E.Salary='+CAST(#Salary as varchar(20)),getdate())
update E SET E.Name=I.Name, E.Salary=I.Salary
FROM EMP E inner join inserted I on I.ID=E.ID
END
update EMP set Name='D' where ID=4
select updatestmt from TrackUpdate
--drop table EMP
--drop table TrackUpdate

How to merge SQL Server data efficiently?

I have three tables in SQL Server where I need to combine all matching rows from all tables into a fourth MergedTable that will contain all the columns from the three individual tables based on the U_ID column.
Is there a way of doing this via T-SQL in a stored procedure, or should I just create a loop function in C#?
Bottom line is this is going to be executed from a command from a website, so it needs to be something I can encapsulate into an MVC project or component.
Here is an example of the tables.
Table 1:
U_ID ClientNumber OrderDate Amount
---------------------------------------------
BB000Kw 1920384 5/14/2013 1093.39
AA000bM 3839484 12/8/2012 584.42
AA000gH 8294848 2/28/2014 4849.38
AA000md 3849484 4/31/2013 590.84
AA000mF 3998398 3/29/2013 448.82
AA000mG 9944848 11/28/2014 98.85
AA000mn 0292938 10/31/2012 300.48
Table 2:
U_ID Name Date
------------------------------------------
AA000bM "Krivis, Jeffrey" 7/1/2002
AA000bv "Saydah, Michael" 7/30/2002
AA000cA "Byrne, Richard" 4/21/2003
AA000dd "McNeil, Joseph" 6/10/2003
AA000dH "Greenberg, Arnold" 1/16/2003
AA000gH "Rich, Elwood" 7/5/2003
AA000id "O'Neill, Robert J." 11/20/2002
AA000jf "Patsey, Richard" 4/22/2003
AA000jr "Jones, Arthur" 7/1/2002
AA000jU "Toff, Ronald" 7/15/2002
AA000k4 "Anderson, Carl" 8/14/2002
BB000Kw "Wilson, Sam" 3/9/2003
Table 3:
U_ID Name
-----------------------------
AA000bM Acme Company
AA000jr Stockwell Industries
BB000ke Gensen Motors
BB999di Falstaff Cards
BB000dl B and R Printing
BB000Kw Go Golf Carts
AA000gH Rich's Sandwiches
Resulting merged table
U_ID ClientNumber OrderDate Amount CustomerName JoinDate CompanyName
-------------------------------------------------------------------------------------------------------
BB000Kw 1920384 5/14/2013 1093.39 "Wilson, Sam" 3/9/2003 Go Golf Carts
AA000bM 3839484 12/8/2012 584.42 "Krivis, Jeffrey" 7/1/2002 Acme Company
AA000gH 8294848 2/28/2014 4849.38 "Rich, Elwood" 7/5/2003 Rich's Sandwiches
Table 1 is the master table that the others are matched to. You can see from the result that there will be only a subset of all the tables based on those that are matched from Table 1.
I'll be using MVC with the Entity Framework 6 and Linq-to-Entities, but if a T-SQL script is more efficient, then I should probably use that instead.
Which is the better way to go to get this result?
If you want to create a new table you can use SELECT ... INTO ... FROM ... query. In your case it would look like this:
SELECT t1.U_ID, t1.ClientNumber, t1.OrderDate, t1.Amount,
t2.Name as CustomerName, t2.Date as JoinDate,
t3.Name as CompanyName
INTO dbo.ResultingMergedTable
FROM Table1 t1
INNER JOIN Table2 t2 ON t1.U_ID = t2.U_ID
INNER JOIN Table3 t3 ON t1.U_ID = t3.U_ID
Keep in mind that if you are looking at really big data table this will take a lot of time to execute.
You can create a 4th table to do what you mentioned but if you are using sql you can create a view to do the same thing. A view is a virtual table. We use this when we partition data as well as make a detailed record like described above.
http://msdn.microsoft.com/en-us/library/ms187956.aspx
http://www.sqlinfo.net/sqlserver/sql_server_VIEWS_the_basics.php
CREATE VIEW DetailView AS
(
SELECT
-- table1
t1.U_ID,
t1.ClientNumber,
t1.OrderDate,
t1.Amount,
-- table2
t2.Name,
t2.Date as [JoinDate],
-- table3
t3.Name as [Company]
FROM
table1 t1
LEFT JOIN
table2 t2
ON t1.U_ID = t2.U_ID
LEFT JOIN
table3 t3
ON t1.U_ID = t3.U_ID
WHERE
t1.U_ID = t2.U_ID
and
t1.U_ID = t3.U_ID
)

fix data property name in gridview

I have 2 table :
table1: name, family, cityID
table2: cityID, cityName
I have a gridview that it's datasource is:
select * from table1, table2 where table1.cityID = table2.cityID
I disable autoCreatColumns
I add 3 columns to my datagrid.
in first column I fix the data property name to name
in second column I fix the data property name to family
but in third colum when I fix the data propery name to table2.cityName It dosent work...
I want to show the city name in third column.
Its an example but in fact, I have cityName in anouther table that I used, and if I use just cityName, makes error
can any body help me?
Thanks...
try to change
select * from table1, table2 where table1.cityID = table2.cityID
To
select table1.name as Name,table1.family as Family,table2.cityName as City from table1, table2 where table1.cityID = table2.cityID
SELECT name,family,cityName from table1 INNER JOIN table2 ON table1.cityID = table2.cityID
As you are doing inner joins with city ids on both tables..U will get matched Table IDs with name,citynames
You don't need to write table2.cityName, just write cityName and it should work.

Get last inserted id

Is there any way I can get the last inserted ID if I am using SQL Server CE? I have 2 tables and when a new record is created, I want to be able to save the ID in the second table too.
SELECT ##IDENTITY
will retrieve the last auto-generated identity value in SQL Server.
I hope this example will help you.
INSERT INTO jobs (job_desc,min_level,max_level) VALUES ('A new job', 25, 100);
SELECT job_id FROM jobs WHERE job_id = ##IDENTITY;
use this query:
INSERT INTO Persons (FirstName) VALUES ('Joe');
SELECT ID AS LastID FROM Persons WHERE ID = ##Identity;
or you can view this link for more info:
http://blog.sqlauthority.com/2007/03/25/sql-server-identity-vs-scope_identity-vs-ident_current-retrieve-last-inserted-identity-of-record/
Assuming higher values of id are always newer, how about:
SELECT TOP 1 id FROM your_table ORDER BY id DESC
or:
SELECT MAX(id) FROM your_table
This worked fine for me
SELECT TOP (1) your_id FROM your_table ORDER BY your_id DESC

Categories