程序如何使用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 语句代替这两个语句(UPDATEINSERT):

 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/

其中一些或多或少严重

[7] If it ain't broke, don't fix it