我是ASP.net的新手,也是UDT的概念。我曾经在PHP上工作,因此我很难理解UDT概念。
这是为将数据从输入表单插入数据库(SQL Server)而编写的存储过程。
代码工作正常,由我公司的高级开发人员编写。
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只是声明临时表/变量的结构。 在块2中,用户传递存储在临时表/变量中的输入数据。
我很难理解 Block 3 和 Block 4
我不明白在INSERT查询之前UPDATE查询是做什么的?
Block 3和Block 4的目的是什么?
(代码工作正常,没有错误。)
答案 0 :(得分:1)
[1]我首先要注意的是这个源代码不是使用另一个表变量(@TP
)而是缺少事务管理而且错过了错误处理。至少有两个语句(最后两个:UPDATE和INSERT)存在在语句级别生成异常/错误的风险(例如)。
[2]我没有看到任何理由再使用一个表变量(@TP
),第一个是参数@Supplier_UDT Supplier_UDT
。它将创建/增加tempdb contention,并且从开发人员的角度来看将创建另一个依赖项(例如:如果我们要在dbo.Supplier
表中更改其中一列的数据类型,那么我们&# 39;还必须更新此@TP
列的存储过程和定义。
[3]注意:两个表变量(@TP
和@Supplier_UDT
)具有相同的列或(至少)一组公共列:ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active
。如果数据类型,NULL能力和约束相同,则不清楚。
[4] Block 3& 4似乎是UPSERT 模式的实现,但对于许多行(注意:UPSERT的大多数示例仅使用一行)。这意味着对于那些已经存在于dbo.Supplier
表中的供应商(SQL模式应该是必需的)UPDATE
语句将更改/更新列SupplierCode, SupplierName, ...
之后的<{1}} em>最新值和新供应商INSERT
已加入dbo.Supplier
表。
正如Dan Guzman在他的评论(+1)中已经提到的那样,可以使用单个UPDATE
语句而不是这两个语句(INSERT
和MERGE
):
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
表提示?请参阅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/
其中一些或多或少严重。