程序如何使用UDT插入数据?
How procedure insert data using UDT?
我对 ASP.net 和其中的 UDT 概念不熟悉。我曾经在 PHP 上工作,所以我很难理解 UDT 的概念。
这是为将输入表单中的数据插入数据库(SQL 服务器)而编写的存储过程。
代码运行良好,由我公司的高级开发人员编写。
CREATE Procedure [dbo].[Save_Supplier]
@Supplier_UDT Supplier_UDT Readonly,
@UserName varchar(80)
AS
Begin
-------------Block 1------
Declare @TP Table(ID int,Suppliercode varchar(80),Suppliername varchar(80),GSTVATNumber int,Description varchar(80),Productlist varchar(80),Bankdetails varchar(80),
pymenttermdescription varchar(80),Currency int,Pendingpayement Varchar(80),pendingorders int,Active bit )
-------------Block 2------
Insert into @TP(ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active)
select ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active from @Supplier_UDT
-------------Block 3------
Update Supplier
set
Suppliercode=a.Suppliercode ,
Suppliername=a.Suppliername
,GSTVATNumber=a.GSTVATNumber
,Description =a.Description
,Productlist=a.Productlist
,Bankdetails=a.Bankdetails
,pymenttermdescription=a.pymenttermdescription
,Currency=a.Currency
,Pendingpayement=a.Pendingpayement
,pendingorders=a.pendingorders
,Active=a.Active
from @TP a inner join Supplier
on a.ID=Supplier.ID
-------------Block 4------
Insert into Supplier(Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active)
select Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active
from @TP where ID not in (select ID from Supplier) and Suppliercode!=''
据我了解,Block 1 只是声明了临时结构table/variable。
在块 2 中,用户传递的输入数据存储在临时 table/variable 中。
我很难理解块 3 和 块 4
我不明白在 INSERT 查询之前 UPDATE 查询在做什么?
Block 3 和 Block 4 的用途是什么?
(代码运行正常,没有错误。)
[1] 关于此源代码,我首先要注意的不是另一个 table 变量 (@TP
) 的使用,而是缺少 事务管理 以及 缺少错误处理 。至少有两个语句(最后两个:UPDATE 和 INSERT)有在语句级别(例如)生成异常/错误的风险。
[2] 我看不出有任何理由再使用一个 table 变量 (@TP
),第一个是参数 @Supplier_UDT Supplier_UDT
。它将 create/increase tempdb contention 并且从开发人员的角度来看将创建另一个依赖项(例如:如果我们要更改 dbo.Supplier
[=67= 中的其中一个列的数据类型] 然后我们还必须更新此存储过程和 @TP
列的定义。
[3] 注意:两个 table 变量(@TP
和 @Supplier_UDT
)具有相同的列或(至少)一组公共列:ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active
.不清楚数据类型、NULL 能力和约束是否相同。
[4] Block 3 & 4 似乎是 UPSERT pattern 的实现,但对于很多行(注意:UPSERT 的大多数示例只使用一个排)。这意味着对于那些 已经 存在于 dbo.Supplier
table 中的供应商(SQL 模式应该是强制性的)UPDATE
声明将 change/update 以下列 SupplierCode, SupplierName, ...
具有 最新 值和新供应商被 INSERT
编辑到 dbo.Supplier
table.
正如 Dan Guzman 在他的评论 (+1) 中已经提到的,可以使用单个 MERGE
语句代替这两个语句(UPDATE
和 INSERT
):
MERGE dbo.Supplier WITH(HOLDLOCK) AS dst -- Destination table
USING @Supplier_UDT AS src ON dst.ID = src.ID -- Source table
WHEN MATCHED THEN
UPDATE
SET
Suppliercode = a.Suppliercode ,
Suppliername = a.Suppliername,
GSTVATNumber = a.GSTVATNumber,
Description = a.Description,
Productlist = a.Productlist,
Bankdetails = a.Bankdetails,
pymenttermdescription = a.pymenttermdescription,
Currency = a.Currency,
Pendingpayement = a.Pendingpayement,
pendingorders = a.pendingorders,
Active = a.Active
WHEN NOT MATCHED AND dst.Suppliercode != '' THEN -- Please make sure that Suppliercode refers to destination table and not to source table
INSERT (Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active)
VALUES (Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active);
[5] 为什么我要使用 HOLDLOCK
table 提示?请参阅 Dan Guzman 的博客:http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
[6] 此外,这里还存在一些关于 MERGE 语句的错误:
https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/
其中一些或多或少严重。
我对 ASP.net 和其中的 UDT 概念不熟悉。我曾经在 PHP 上工作,所以我很难理解 UDT 的概念。
这是为将输入表单中的数据插入数据库(SQL 服务器)而编写的存储过程。
代码运行良好,由我公司的高级开发人员编写。
CREATE Procedure [dbo].[Save_Supplier]
@Supplier_UDT Supplier_UDT Readonly,
@UserName varchar(80)
AS
Begin
-------------Block 1------
Declare @TP Table(ID int,Suppliercode varchar(80),Suppliername varchar(80),GSTVATNumber int,Description varchar(80),Productlist varchar(80),Bankdetails varchar(80),
pymenttermdescription varchar(80),Currency int,Pendingpayement Varchar(80),pendingorders int,Active bit )
-------------Block 2------
Insert into @TP(ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active)
select ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active from @Supplier_UDT
-------------Block 3------
Update Supplier
set
Suppliercode=a.Suppliercode ,
Suppliername=a.Suppliername
,GSTVATNumber=a.GSTVATNumber
,Description =a.Description
,Productlist=a.Productlist
,Bankdetails=a.Bankdetails
,pymenttermdescription=a.pymenttermdescription
,Currency=a.Currency
,Pendingpayement=a.Pendingpayement
,pendingorders=a.pendingorders
,Active=a.Active
from @TP a inner join Supplier
on a.ID=Supplier.ID
-------------Block 4------
Insert into Supplier(Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active)
select Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active
from @TP where ID not in (select ID from Supplier) and Suppliercode!=''
据我了解,Block 1 只是声明了临时结构table/variable。 在块 2 中,用户传递的输入数据存储在临时 table/variable 中。
我很难理解块 3 和 块 4
我不明白在 INSERT 查询之前 UPDATE 查询在做什么?
Block 3 和 Block 4 的用途是什么?
(代码运行正常,没有错误。)
[1] 关于此源代码,我首先要注意的不是另一个 table 变量 (@TP
) 的使用,而是缺少 事务管理 以及 缺少错误处理 。至少有两个语句(最后两个:UPDATE 和 INSERT)有在语句级别(例如)生成异常/错误的风险。
[2] 我看不出有任何理由再使用一个 table 变量 (@TP
),第一个是参数 @Supplier_UDT Supplier_UDT
。它将 create/increase tempdb contention 并且从开发人员的角度来看将创建另一个依赖项(例如:如果我们要更改 dbo.Supplier
[=67= 中的其中一个列的数据类型] 然后我们还必须更新此存储过程和 @TP
列的定义。
[3] 注意:两个 table 变量(@TP
和 @Supplier_UDT
)具有相同的列或(至少)一组公共列:ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active
.不清楚数据类型、NULL 能力和约束是否相同。
[4] Block 3 & 4 似乎是 UPSERT pattern 的实现,但对于很多行(注意:UPSERT 的大多数示例只使用一个排)。这意味着对于那些 已经 存在于 dbo.Supplier
table 中的供应商(SQL 模式应该是强制性的)UPDATE
声明将 change/update 以下列 SupplierCode, SupplierName, ...
具有 最新 值和新供应商被 INSERT
编辑到 dbo.Supplier
table.
正如 Dan Guzman 在他的评论 (+1) 中已经提到的,可以使用单个 MERGE
语句代替这两个语句(UPDATE
和 INSERT
):
MERGE dbo.Supplier WITH(HOLDLOCK) AS dst -- Destination table
USING @Supplier_UDT AS src ON dst.ID = src.ID -- Source table
WHEN MATCHED THEN
UPDATE
SET
Suppliercode = a.Suppliercode ,
Suppliername = a.Suppliername,
GSTVATNumber = a.GSTVATNumber,
Description = a.Description,
Productlist = a.Productlist,
Bankdetails = a.Bankdetails,
pymenttermdescription = a.pymenttermdescription,
Currency = a.Currency,
Pendingpayement = a.Pendingpayement,
pendingorders = a.pendingorders,
Active = a.Active
WHEN NOT MATCHED AND dst.Suppliercode != '' THEN -- Please make sure that Suppliercode refers to destination table and not to source table
INSERT (Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active)
VALUES (Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active);
[5] 为什么我要使用 HOLDLOCK
table 提示?请参阅 Dan Guzman 的博客:http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx
[6] 此外,这里还存在一些关于 MERGE 语句的错误: https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/
其中一些或多或少严重。