我有一个表,我在其中为员工插入行,但下次当我想插入行时我不想再插入该员工的数据只是想要更新所需的列,如果它退出那里,如果没有然后创建新行
我们如何在SQL Server 2005中执行此操作?
我正在使用jsp
我的疑问是
String sql="insert into table1(id,name,itemname,itemcatName,itemQty)values('val1','val2','val3','val4','val5')";
Run Code Online (Sandbox Code Playgroud)
如果它是第一次然后将其插入数据库,否则如果存在更新它
怎么做?
mar*_*c_s 58
尝试检查是否存在:
IF NOT EXISTS (SELECT * FROM dbo.Employee WHERE ID = @SomeID)
INSERT INTO dbo.Employee(Col1, ..., ColN)
VALUES(Val1, .., ValN)
ELSE
UPDATE dbo.Employee
SET Col1 = Val1, Col2 = Val2, ...., ColN = ValN
WHERE ID = @SomeID
Run Code Online (Sandbox Code Playgroud)
您可以轻松地将其包装到存储过程中,并从外部调用该存储过程(例如,从C#或您正在使用的任何编程语言).
更新:要么你可以在一个长字符串中编写整个语句(可行 - 但不是非常有用) - 或者你可以将它包装到存储过程中:
CREATE PROCEDURE dbo.InsertOrUpdateEmployee
@ID INT,
@Name VARCHAR(50),
@ItemName VARCHAR(50),
@ItemCatName VARCHAR(50),
@ItemQty DECIMAL(15,2)
AS BEGIN
IF NOT EXISTS (SELECT * FROM dbo.Table1 WHERE ID = @ID)
INSERT INTO dbo.Table1(ID, Name, ItemName, ItemCatName, ItemQty)
VALUES(@ID, @Name, @ItemName, @ItemCatName, @ItemQty)
ELSE
UPDATE dbo.Table1
SET Name = @Name,
ItemName = @ItemName,
ItemCatName = @ItemCatName,
ItemQty = @ItemQty
WHERE ID = @ID
END
Run Code Online (Sandbox Code Playgroud)
然后从ADO.NET代码中调用该存储过程
Evg*_*orb 28
您可以@@ROWCOUNT用来检查是否应该插入或更新行:
update table1
set name = 'val2', itemname = 'val3', itemcatName = 'val4', itemQty = 'val5'
where id = 'val1'
if @@ROWCOUNT = 0
insert into table1(id, name, itemname, itemcatName, itemQty)
values('val1', 'val2', 'val3', 'val4', 'val5')
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果更新失败,将插入新行
pro*_*ams 13
以下是 Michael J. Swart 关于此事的一篇有用文章,其中涵盖了UPSERT在 SQL Server 中实现的不同模式和反模式:https :
//michaeljswart.com/2017/07/sql-server-upsert-patterns-and-antipatterns/
它解决了相关的并发问题(主键冲突、死锁)——此处提供的所有答案都被视为本文中的反模式(使用触发器的 @Bridge 解决方案除外,此处未涵盖)。
以下是文章的摘录,其中包含作者首选的解决方案:
在带有锁提示的可序列化事务中:
CREATE PROCEDURE s_AccountDetails_Upsert ( @Email nvarchar(4000), @Etc nvarchar(max) )
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRAN
IF EXISTS ( SELECT * FROM dbo.AccountDetails WITH (UPDLOCK) WHERE Email = @Email )
UPDATE dbo.AccountDetails
SET Etc = @Etc
WHERE Email = @Email;
ELSE
INSERT dbo.AccountDetails ( Email, Etc )
VALUES ( @Email, @Etc );
COMMIT
Run Code Online (Sandbox Code Playgroud)
在stackoverflow上还有一个相关的问题和答案:Insert Update stored proc on SQL Server
(我的答案如下,但之后我意识到在插入MySQL表或更新(例如存在)时有更好的问题和答案)
您可以检查该行是否存在,然后INSERT或UPDATE,但这可以保证您将执行两个SQL操作而不是一个:
更好的解决方案是始终首先更新,如果没有更新行,则执行INSERT,如下所示:
update table1
set name = 'val2', itemname = 'val3', itemcatName = 'val4', itemQty = 'val5'
where id = 'val1'
if @@ROWCOUNT = 0
insert into table1(id, name, itemname, itemcatName, itemQty)
values('val1', 'val2', 'val3', 'val4', 'val5')
Run Code Online (Sandbox Code Playgroud)
这将执行一个SQL操作或两个SQL操作,具体取决于该行是否已存在.
但如果性能确实是一个问题,那么你需要弄清楚操作是否更可能是INSERT或UPDATE.如果UPDATE更常见,请执行以上操作.如果INSERT更常见,您可以反向执行,但您必须添加错误处理.
BEGIN TRY
insert into table1(id, name, itemname, itemcatName, itemQty)
values('val1', 'val2', 'val3', 'val4', 'val5')
END TRY
BEGIN CATCH
update table1
set name = 'val2', itemname = 'val3', itemcatName = 'val4', itemQty = 'val5'
where id = 'val1'
END CATCH
Run Code Online (Sandbox Code Playgroud)
要确定是否需要执行UPDATE或INSERT,您必须在单个TRANSACTION中执行两项操作.从理论上讲,在第一次UPDATE或INSERT(甚至是EXISTS检查)之后,但在下一个INSERT/UPDATE语句之前,数据库可能已经改变,导致第二个语句无论如何都会失败.这非常罕见,交易的开销可能不值得.
或者,您可以使用名为MERGE的单个SQL操作来执行INSERT或UPDATE,但这对于此单行操作来说也可能过度.
考虑阅读有关SQL事务语句,竞争条件,SQL MERGE语句的内容.
您可以使用INSTEAD OF INSERT表上的触发器来执行此操作,该触发器检查该行是否存在,然后根据该行是否已存在进行更新/插入。MSDN上有一个关于如何针对 SQL Server 2000+ 执行此操作的示例:
CREATE TRIGGER IO_Trig_INS_Employee ON Employee
INSTEAD OF INSERT
AS
BEGIN
SET NOCOUNT ON
-- Check for duplicate Person. If no duplicate, do an insert.
IF (NOT EXISTS (SELECT P.SSN
FROM Person P, inserted I
WHERE P.SSN = I.SSN))
INSERT INTO Person
SELECT SSN,Name,Address,Birthdate
FROM inserted
ELSE
-- Log attempt to insert duplicate Person row in PersonDuplicates table.
INSERT INTO PersonDuplicates
SELECT SSN,Name,Address,Birthdate,SUSER_SNAME(),GETDATE()
FROM inserted
-- Check for duplicate Employee. If no duplicate, do an insert.
IF (NOT EXISTS (SELECT E.SSN
FROM EmployeeTable E, inserted
WHERE E.SSN = inserted.SSN))
INSERT INTO EmployeeTable
SELECT EmployeeID,SSN, Department, Salary
FROM inserted
ELSE
--If duplicate, change to UPDATE so that there will not
--be a duplicate key violation error.
UPDATE EmployeeTable
SET EmployeeID = I.EmployeeID,
Department = I.Department,
Salary = I.Salary
FROM EmployeeTable E, inserted I
WHERE E.SSN = I.SSN
END
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
77588 次 |
| 最近记录: |