我有一个简单的表,其中包含2列CarId int,主键和CarName,varchar。
我需要创建一个接受汽车列表的存储过程。如果车辆CarId
不存在,我想插入那辆车,如果已经存在,我想更新它。
我创建了一个用户定义的表格类型CarType
:
CREATE TYPE dbo.CarType
AS TABLE
(
CARID int null,
CARNAME varchar(800) not null,
);
和存储过程InsertCars
:
CREATE PROCEDURE dbo.InsertCars
@Cars AS CarType READONLY
AS
DECLARE @CarCount INT = 0;
DECLARE @Counter INT = 0;
BEGIN
SET @CarsCount = (SELECT COUNT(CarId) FROM @Cars);
WHILE(@Counter < @CarsCount)
BEGIN TRY
--how get item from list Cars?
@CurrentCar = Cars(@Counter)
IF EXISTS(SELECT 1 FROM Cars WHERE CarsId = CurrentCar.CarId)
--if doesn’t exist insert
BEGIN
INSERT INTO CARS(CARID, CARNAME)
SELECT * FROM @CurrentCar;
END
ELSE
BEGIN
--if exist update
END
END
SET @Counter= @Counter + 1;
END TRY
BEGIN CATCH
Print (ERROR_MESSAGE());
END CATCH
END
我不知道如何从汽车列表(存储过程中的参数Cars
)获取当前汽车循环。
或者针对这个问题的优雅解决方案。
答案 0 :(得分:3)
看来你可能会摆脱循环:
CREATE PROCEDURE dbo.InsertCars
@Cars AS CarType READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE c
SET c.CARNAME = c2.CARNAME
FROM Cars c
JOIN @Cars c2 on c2.CARID = c.CARID;
INSERT INTO Cars(CARID, CARNAME)
SELECT c.CARID, c.CARNAME
FROM @Cars c
WHERE NOT EXISTS (SELECT 1 FROM Cars WHERE CARID = c.CARID);
END
或(使用merge
构造):
CREATE PROCEDURE dbo.InsertCars
@Cars AS CarType READONLY
AS
BEGIN
SET NOCOUNT ON;
MERGE Cars AS target
USING (SELECT CARID, CARNAME FROM @Cars) AS source (CARID, CARNAME)
ON (target.CARID = source.CARID)
WHEN MATCHED THEN
UPDATE SET CARNAME = source.CARNAME
WHEN NOT MATCHED THEN
INSERT (CARID, CARNAME)
VALUES (source.CARID, source.CARNAME);
END