Table 具有主键更改的值参数
Table valued parameter with primary keys changes
我刚开始在 sql 服务器 2008 中使用 table 值参数来更新 table。基本上,我逐列创建用户定义的 table 类型映射到现有 table,并将其用作 table 值参数,将数据传递到服务器以进行删除、更新和插入。在大多数情况下,效果很好。但是,对于具有复合主键的 table,当部分键发生更改时,此方法将失败,因为 tvp 仅包含一组键值(当前或原始键值)。我的问题是处理此类案件的最佳方式是什么?我是否必须在 table 类型定义中添加第二组主键列?
一个简化的例子:
表格:
CREATE TABLE [dbo].[Prices](
[ID] [int] NOT NULL PRIMARY KEY,
[Date] [smalldatetime] NOT NULL PRIMARY KEY,
[Value] [float] NOT NULL,
CONSTRAINT [PK_Prices] PRIMARY KEY CLUSTERED
(
[ID] ASC,
[Date] ASC
)
)
Table Type
CREATE TYPE [dbo].[tvp_Prices] AS TABLE(
[ID] [int] NOT NULL,
[Date] [smalldatetime] NOT NULL,
[Value] [float] NOT NULL
)
Add some data to the table
Insert Into [dbo].[Prices] Values (1, '1/1/2015', 1.2)
Insert Into [dbo].[Prices] Values (1, '1/2/2015', 1.3)
Insert Into [dbo].[Prices] Values (2, '1/1/2015', 1.4)
Insert Into [dbo].[Prices] Values (2, '1/2/2015', 1.5)
in c#, load the Prices to DataTable pricesTable,
update some value:
pricesTable.Rows[1]["Date"] = new DateTime(2015, 1, 3);
现在的问题是如何使用 table 值参数 (tvp_Prices) 将更改保存回服务器?
Table值参数用于将多行数据通过参数传递给例如存储过程。在您的情况下,用例可能是下一个:
CREATE TYPE [dbo].[tvp_Prices] AS TABLE(
[ID] [int] NOT NULL,
[Date] [smalldatetime] NOT NULL,
[Value] [float] NOT NULL
);
CREATE TABLE [dbo].[Prices](
[ID] [int] NOT NULL PRIMARY KEY,
[Date] [smalldatetime] NOT NULL PRIMARY KEY,
[Value] [float] NOT NULL,
CONSTRAINT [PK_Prices] PRIMARY KEY CLUSTERED
(
[ID] ASC,
[Date] ASC
)
);
CREATE PROC dbo.use_Prices
(
@prices [dbo].[tvp_Prices] READONLY
)
AS BEGIN
INSERT INTO [dbo].[Prices] ([ID], [Date], [Value])
SELECT * FROM @prices;
END
-- usage ---------------------------------
DECLARE
@prices [dbo].[tvp_Prices];
Insert Into @prices Values (1, '1/1/2015', 1.2)
Insert Into @prices Values (1, '1/2/2015', 1.3)
Insert Into @prices Values (2, '1/1/2015', 1.4)
Insert Into @prices Values (2, '1/2/2015', 1.5)
SELECT * FROM [dbo].[Prices]
EXEC dbo.use_Prices @prices;
SELECT * FROM [dbo].[Prices]
结果
ID Date Value
-----------------------------
-
ID Date Value
-----------------------------
1 2015-01-01 00:00:00 1.2
1 2015-01-02 00:00:00 1.3
2 2015-01-01 00:00:00 1.4
2 2015-01-02 00:00:00 1.5
更新示例
CREATE PROC dbo.use_UpdatePrices
(
@prices [dbo].[tvp_Prices] READONLY
)
AS BEGIN
-- update values by the PK
UPDATE p
SET
p.[Value] = p1.[Value]
FROM [dbo].[Prices] p
JOIN @prices p1 ON p1.ID = p.[ID]
AND p1.[Date] = p.[Date];
END
Truncate table [dbo].[Prices]
Insert Into [dbo].[Prices] Values (1, '1/1/2015', 1.2)
Insert Into [dbo].[Prices] Values (1, '1/2/2015', 1.3)
Insert Into [dbo].[Prices] Values (2, '1/1/2015', 1.4)
Insert Into [dbo].[Prices] Values (2, '1/2/2015', 1.5)
-- usage -----------------------------------
DECLARE
@prices [dbo].[tvp_Prices];
-- values to update
Insert Into @prices Values (1, '1/1/2015', 10.10)
Insert Into @prices Values (1, '1/2/2015', 11.11)
SELECT * FROM [dbo].[Prices]
EXEC dbo.use_UpdatePrices @prices;
SELECT * FROM [dbo].[Prices]
输出
ID Date Value
-----------------------------
1 2015-01-01 00:00:00 1.2
1 2015-01-02 00:00:00 1.3
2 2015-01-01 00:00:00 1.4
2 2015-01-02 00:00:00 1.5
ID Date Value
-----------------------------
1 2015-01-01 00:00:00 10.1
1 2015-01-02 00:00:00 11.11
2 2015-01-01 00:00:00 1.4
2 2015-01-02 00:00:00 1.5
我刚开始在 sql 服务器 2008 中使用 table 值参数来更新 table。基本上,我逐列创建用户定义的 table 类型映射到现有 table,并将其用作 table 值参数,将数据传递到服务器以进行删除、更新和插入。在大多数情况下,效果很好。但是,对于具有复合主键的 table,当部分键发生更改时,此方法将失败,因为 tvp 仅包含一组键值(当前或原始键值)。我的问题是处理此类案件的最佳方式是什么?我是否必须在 table 类型定义中添加第二组主键列?
一个简化的例子: 表格:
CREATE TABLE [dbo].[Prices](
[ID] [int] NOT NULL PRIMARY KEY,
[Date] [smalldatetime] NOT NULL PRIMARY KEY,
[Value] [float] NOT NULL,
CONSTRAINT [PK_Prices] PRIMARY KEY CLUSTERED
(
[ID] ASC,
[Date] ASC
)
)
Table Type
CREATE TYPE [dbo].[tvp_Prices] AS TABLE(
[ID] [int] NOT NULL,
[Date] [smalldatetime] NOT NULL,
[Value] [float] NOT NULL
)
Add some data to the table
Insert Into [dbo].[Prices] Values (1, '1/1/2015', 1.2)
Insert Into [dbo].[Prices] Values (1, '1/2/2015', 1.3)
Insert Into [dbo].[Prices] Values (2, '1/1/2015', 1.4)
Insert Into [dbo].[Prices] Values (2, '1/2/2015', 1.5)
in c#, load the Prices to DataTable pricesTable,
update some value:
pricesTable.Rows[1]["Date"] = new DateTime(2015, 1, 3);
现在的问题是如何使用 table 值参数 (tvp_Prices) 将更改保存回服务器?
Table值参数用于将多行数据通过参数传递给例如存储过程。在您的情况下,用例可能是下一个:
CREATE TYPE [dbo].[tvp_Prices] AS TABLE(
[ID] [int] NOT NULL,
[Date] [smalldatetime] NOT NULL,
[Value] [float] NOT NULL
);
CREATE TABLE [dbo].[Prices](
[ID] [int] NOT NULL PRIMARY KEY,
[Date] [smalldatetime] NOT NULL PRIMARY KEY,
[Value] [float] NOT NULL,
CONSTRAINT [PK_Prices] PRIMARY KEY CLUSTERED
(
[ID] ASC,
[Date] ASC
)
);
CREATE PROC dbo.use_Prices
(
@prices [dbo].[tvp_Prices] READONLY
)
AS BEGIN
INSERT INTO [dbo].[Prices] ([ID], [Date], [Value])
SELECT * FROM @prices;
END
-- usage ---------------------------------
DECLARE
@prices [dbo].[tvp_Prices];
Insert Into @prices Values (1, '1/1/2015', 1.2)
Insert Into @prices Values (1, '1/2/2015', 1.3)
Insert Into @prices Values (2, '1/1/2015', 1.4)
Insert Into @prices Values (2, '1/2/2015', 1.5)
SELECT * FROM [dbo].[Prices]
EXEC dbo.use_Prices @prices;
SELECT * FROM [dbo].[Prices]
结果
ID Date Value
-----------------------------
-
ID Date Value
-----------------------------
1 2015-01-01 00:00:00 1.2
1 2015-01-02 00:00:00 1.3
2 2015-01-01 00:00:00 1.4
2 2015-01-02 00:00:00 1.5
更新示例
CREATE PROC dbo.use_UpdatePrices
(
@prices [dbo].[tvp_Prices] READONLY
)
AS BEGIN
-- update values by the PK
UPDATE p
SET
p.[Value] = p1.[Value]
FROM [dbo].[Prices] p
JOIN @prices p1 ON p1.ID = p.[ID]
AND p1.[Date] = p.[Date];
END
Truncate table [dbo].[Prices]
Insert Into [dbo].[Prices] Values (1, '1/1/2015', 1.2)
Insert Into [dbo].[Prices] Values (1, '1/2/2015', 1.3)
Insert Into [dbo].[Prices] Values (2, '1/1/2015', 1.4)
Insert Into [dbo].[Prices] Values (2, '1/2/2015', 1.5)
-- usage -----------------------------------
DECLARE
@prices [dbo].[tvp_Prices];
-- values to update
Insert Into @prices Values (1, '1/1/2015', 10.10)
Insert Into @prices Values (1, '1/2/2015', 11.11)
SELECT * FROM [dbo].[Prices]
EXEC dbo.use_UpdatePrices @prices;
SELECT * FROM [dbo].[Prices]
输出
ID Date Value
-----------------------------
1 2015-01-01 00:00:00 1.2
1 2015-01-02 00:00:00 1.3
2 2015-01-01 00:00:00 1.4
2 2015-01-02 00:00:00 1.5
ID Date Value
-----------------------------
1 2015-01-01 00:00:00 10.1
1 2015-01-02 00:00:00 11.11
2 2015-01-01 00:00:00 1.4
2 2015-01-02 00:00:00 1.5