我有一个存储过程,将“表值参数”作为输入。它有大约15-20列。 我想在没有MERGE的情况下执行插入/更新操作,因为MERGE在table上有锁。通过做研究,我知道,游标也可以使用。但是游标会降低性能。 我发现了这篇文章(https://www.dotnettricks.com/learn/sqlserver/sql-server-cursor-alternatives),在里面的while循环中,我们获取了每个列变量,对于列数大于10的表,这将是乏味的。那么,还有其他选择吗?
答案 0 :(得分:2)
您可以创建一个存储过程,并像下面的代码一样传递您的参数:
CREATE PROCEDURE [dbo].[MyStoredProcedure]
@TableValue [dbo].[TABLETYPE] READONLY
AS
BEGIN
UPDATE [dbo].[MyTable]
SET Name = T.Name
FROM [dbo].[MyTable]
INNER JOIN @TableValue AS T ON T.Id = [dbo].[MyTable].Id
WHERE T.Name <> [dbo].[MyTable].Name
INSERT INTO [dbo].[MyTable](Id,Name)
SELECT Id , Name
FROM @TableValue AS T
WHERE NOT EXISTS(SELECT *
FROM [dbo].[MyTable]
WHERE Id = T.Id)
END
GO
首先更新现有记录,然后插入新行。
答案 1 :(得分:-2)
我为您创建了一个示例。这很容易。 您可以将其放入存储过程中:
DECLARE @TABLE_NAME VARCHAR(100)
DECLARE @TABLE_NAME_DEST VARCHAR(100)
DECLARE @List VARCHAR(8000)
DECLARE @SQL VARCHAR(4000)
SET @TABLE_NAME = 'Employee'
SET @TABLE_NAME_DEST = 'Employee_DEST'
SELECT @List = COALESCE(@List + ', ', '') + Column_Name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = @TABLE_NAME
-- Prevent Injection
IF (EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @TABLE_NAME ))
BEGIN
SET @SQL = 'INSERT INTO [' + @TABLE_NAME_DEST +'] (' + @List +')' +char(10)
SET @SQL = @SQL + 'SELECT ' + @List + char(10) + 'FROM ' + @TABLE_NAME
print @SQL
END
类似于SQL更新。