【问题标题】:Insert values into multiple SQL tables将值插入多个 SQL 表
【发布时间】:2009-03-16 06:24:25
【问题描述】:

在 C# 和 SQL server 中插入响应许多表的表数据的好方法是什么?

例如说我有以下表格:

Products: PK=PID, Product_Name
Build: PK:BID, Build_Number, FK:PID
Files: PK:FID, File_Name, FK:PID
FileDetails: PK:FDID, FK:FID, FK:BID, File_Size, File_Version

所以所有的主键都是自动递增的数字

所以我有一个 xml 文件,其中有一行信息,例如:

Product_Name ,Build_Number,File_Name,File_Size,File_Version
FooCreator1.0,112233      ,foo.exe  ,123456   ,3.5
FooCreator1.0,112233      ,bar.exe  ,234567   ,1.5

我希望能够将行添加到我的表中。想象一下我的数据库是空的。

我是否必须首先添加所有产品,然后添加所有构建,然后添加所有文件,然后加入所有表,然后添加所有文件详细信息?

编辑:我将有大约 20,000 行,并且我将在最终唯一表中每行存储大约 40 个值。

【问题讨论】:

    标签: c# sql sql-server


    【解决方案1】:

    这是我会做的,虽然我不确定这是最好的方法:

    declare @PID bigint
    declare @BID bigint
    declare @FID bigint
    
    insert into Products (Product_Name)
    values ('FooCreator1.0')
    
    select @PID = scope_identity()
    
    insert into Build (Build_Number, PID)
    values (112233, @PID)
    
    select @BID = scope_identity()
    
    insert into Files (File_Name, PID)
    values ('foo.exe', @PID)
    
    select @FID = scope_identity()
    
    insert into FileDetails (FID, BID, File_Size, File_Version)
    values (@FID, @BID, 123456, '3.5')
    

    类似的东西?可能想在事务中运行整个事情,以防出现任何问题。

    【讨论】:

    • 除了 product_name 是 'FooCreator1.0' 和 build_number 是 '112233'(我猜是误读了“.”和“,”),看起来还不错。
    • +1 为 sp。数据库应该维护自己的完整性,而不是依赖 UI 以正确的顺序插入正确的行。
    • 如果插入 int 文件失败,因为具有相同 pid 的文件已经存在,会发生什么?
    • files 表中的 PID 是否有唯一约束?如果不是,则允许您拥有多个具有相同 PID 值的 Files 记录,因为它不是主键,也不是唯一的。
    【解决方案2】:

    基本上,是的(最后一个0。但是如何你可能取决于所涉及的行数。如果你有几百(可能一千左右),那么你可以使用一些东西很高兴地喜欢 LINQ-to-SQL:创建您需要的对象,并使用InsertOnSubmit 将必要的项目添加到数据上下文中。最后,调用SubmitChanges(工作完成;其他 ORM 工具将类似地工作)。

    如果您有数万行(或其他),那么您可能只需将整个 xml 放入数据库(可能是带有 xml 参数的存储过程)。在数据库中使用sql/xml,从xml参数做4条INSERT语句。

    对于数十万/数百万行,您需要使用 SqlBulkCopy 将数据推送到临时表中(布局如您的示例) - 然后使用存储过程执行 4 INSERTs .让 xml 表现得像 csv 是 bespoke data reader 的工作。

    【讨论】:

      【解决方案3】:

      是的。打开一个事务并按后续顺序添加行。您必须先添加产品并获取其 ID 才能添加构建并将该 ID 用作外键。您也可以将其编写为存储过程。 SQL Server 没有列表类型的过程参数,但如果您想一次性传递这样的复杂结构,并且您已经拥有 XML 格式的文件,则可以传递该文档,如 SQL Server 2005(您没有t 说你使用的是哪个版本)支持XML parameters。有了它,您就可以在存储过程中使用 XPath 来查询内容并构建数据。

      【讨论】:

        【解决方案4】:

        C#/.NET 可能有更好的方法,但通常的方法是按照您的建议(大致)。对于 XML 文件中的每一行,您必须先创建 PRODUCT(如果已经存在,则获取其 PID)。

        如果不存在则添加 BUILD(如果存在则获取 BID)。

        如果 FILE 不存在则添加(如果存在则获取 FID)。

        然后在FILEDETAILS中添加或更新多对多关系。

        每个插入/选择操作(产品、构建、文件)将按如下方式进行:

        insert into PRODUCTS (PRODUCT_NAME) VALUES ('FooCreator1.0')
        // ignore errors from preceding statement
        select PID from PRODUCTS where PRODUCT_NAME = 'FooCreator1.0'
        

        因为,如果有人在创建该产品时击败了你,你只需要它的 PID 供以后插入。

        【讨论】:

          【解决方案5】:

          我建议使用Andy Whitestored procedure 中提出的插入语句,原因如下:

          • 性能,允许数据库编译和缓存语句。
          • 安全性,以输入数据作为参数调用 SP 将限制恶意值的使用。
          • 将 DB 结构与客户端分开,如果/当您想要更改架构时,您将不需要重新编译。
          • 可以在不受客户端干扰的情况下添加内部日志记录/错误处理。

          当然一切都取决于操作的使用情况。如果是一次性操作,那可能就大材小用了。

          您应该将语句封装在transaction 中以确保全部或全部完成,甚至使用TRY-CATCH。但正如我所写,这一切都取决于操作的使用情况。

          /JB

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-04-11
            • 1970-01-01
            • 2011-06-14
            • 2015-08-08
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多