【问题标题】:How procedure insert data using UDT?程序如何使用UDT插入数据?
【发布时间】:2017-06-30 13:58:14
【问题描述】:

我是 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 3Block 4

我不明白在 INSERT 查询之前 UPDATE 查询在做什么?

Block 3 和 Block 4 的目的是什么?

(代码运行正常,没有错误。)

【问题讨论】:

  • 我们无法知道贵公司业务逻辑的原因。这也是 SO 的题外话
  • 块 1/2 似乎是多余的,因为 @TP 可以替换为 @Supplier_UDT。块 3 使用来自 @TP 的值和匹配的 ID 更新 Supplier 表,如果 @TP 的 ID 不在 Supplier 中,则最后插入将它们添加为新行。
  • 不需要表变量来保存表值参数的内容。您可以像使用表格一样使用参数。
  • 可以使用单个MERGE 语句同时执行INSERTUPDATE。通过消除局部表变量,proc 也可以是一条语句。
  • 只需在第 3 块和第 4 块中使用您现有的代码。但不要使用@TP,而是使用您的表参数。

标签: c# asp.net sql-server stored-procedures user-defined-types


【解决方案1】:

[1] 关于此源代码,我首先要注意的不是另一个表变量 (@TP) 的使用,而是缺少事务管理以及缺少错误处理。至少有两条语句(最后两条:UPDATE 和 INSERT)存在在语句级别(例如)产生异常/错误的风险。

[2] 我看不出有任何理由再使用一个表变量 (@TP),第一个是参数 @Supplier_UDT Supplier_UDT。它将创建/增加tempdb contention 并且从开发人员的角度来看将创建另一个依赖项(例如:如果我们要更改dbo.Supplier 表中这些列之一的数据类型,那么我们也必须更新这个@TP 列的存储过程和定义。

[3] 注意:两个表变量(@TP@Supplier_UDT)具有相同的列或(至少)一组公共列:ID ,Suppliercode ,Suppliername,GSTVATNumber,Description ,Productlist,Bankdetails,pymenttermdescription,Currency,Pendingpayement ,pendingorders ,Active。不清楚数据类型、NULL 能力和约束是否相同。

[4] 块 3 和 4 似乎是 UPSERT pattern 的实现,但是对于许多行(注意:UPSERT 的大多数示例只使用一行)。这意味着对于那些已经存在于dbo.Supplier 表中的供应商(SQL 模式应该是强制性的)UPDATE 语句将使用 latest更改/更新后续列SupplierCode, SupplierName, ... > 价值观和新供应商被INSERTed 到dbo.Supplier 表中。

正如 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 表提示?请参阅 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

【讨论】:

  • 哇,这是一个了不起的指导。非常感谢。并感谢您的程序,我将参考创建新程序:)
猜你喜欢
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2016-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多