【问题标题】:SQL: Use the same string for both INSERT and UPDATE?SQL:对 INSERT 和 UPDATE 使用相同的字符串?
【发布时间】:2010-10-21 20:58:39
【问题描述】:

我一直使用的 INSERT 语法是这样的

INSERT INTO TableName VALUES (...)

我一直使用的 UPDATE 语法是

UPDATE TableName SET ColumnName=Value WHERE ...

所以在我的所有代码中,我必须生成 2 个字符串,这会导致类似这样的结果

insertStr = "(27, 'John Brown', 102)";
updateStr = "ID=27, Name='John Brown', ItemID=102";

然后分别使用

"UPDATE TableName SET " + updateStr + " WHERE ID=27 " +
"IF @@ROWCOUNT=0 "+
"INSERT INTO TableName VALUES (" + insertStr + ")"

当我使用大约 30 列的表格时,它开始困扰我。

我们不能只生成一个用于 INSERT 和 UPDATE 的字符串吗?

例如。在 UPDATE 语句上使用上面的 insertStr 或在 INSERT 语句上使用 updateStr,还是一种全新的方式?

【问题讨论】:

    标签: sql insert sql-update


    【解决方案1】:

    我认为您需要一种全新的方法。您对 SQL Injection 持开放态度。向我们提供一些示例代码,了解如何获取数据输入并将语句发送到数据库。 alt text http://goose.ycp.edu/~weddins/440/S09%20IFS440%20Bobby%20Drop%20Tables.PNG

    【讨论】:

    • 我同意。如果这是生产代码,您至少应该使用参数化语句。告诉我们您使用的是什么语言,也许您可​​以找到更好的方法,例如对象持久性。
    • 这有什么关系?问题是关于创建适用于两个语句的字符串。
    • 学习更好的编程实践总是相关的。
    • @womp 遇见幽默。幽默遇见@womp。许多开发人员不知道 SQL 注入。这只是提醒人们注意它的一种有趣方式。
    • 套用运动玩的问题不是人,这显然是插入/更新 sql 不兼容的长期已知问题。是的,琴弦可能会受到攻击——但这不是问题!
    【解决方案2】:

    据我所知,您所描述的内容在 ANSI SQL 或我所知道的任何扩展中是不可能的。但是,我最熟悉 MySQL,它可能完全取决于您使用的 RDBMS。例如,MySQL 具有“INSERT ... ON DUPLICATE KEY UPDATE ...”语法,这与您在此处发布的类似,并将 INSERT 查询与 UPDATE 查询结合在一起。好处是您将两种可能的操作组合到一个查询中,但是,查询的 INSERT 和 UPDATE 部分是不同的。

    一般来说,这类事情可以通过应用程序中的 ORM 层抽象出来。就原始 SQL 而言,我会对任何按照您描述的方式工作的语法感兴趣。

    【讨论】:

      【解决方案3】:

      某些 DBMS 有一个扩展来执行此操作,但您为什么不提供一个功能来为您执行此操作?我们以前实际上已经这样做过。

      我不确定您使用的是什么语言,但它可能有关联数组,您可以在其中编写如下内容:

      pk{"ID"}   = "27"
      val{"Name"} = "'John Brown'"
      val{"ItemID"} = "102"
      upsert ("MyTable", pk, val)
      

      如果它没有关联数组,您可以使用多个基于整数的字符串数组来模拟它们。

      在我们的upsert() 函数中,我们只是构造了一个字符串(update,如果update 失败,则为insert)并将其传递给我们的 DBMS。我们将主键与其他字段分开,因为这样可以更轻松地构建更新语句(主键列在 where 子句中,其他列只是设置)。

      上述调用的结果将导致以下 SQL(我们对失败的 update 进行了不同的检查,但我已将您的 @@rowcount 放入此示例中):

      update MyTable set
          Name = 'John Brown',
          ItemID = 102
          where ID = 27
      if @@rowcount=0
          insert into MyTable (ID, Name, ItemID) values (
              27,
              'John Brown',
              102
          )
      

      这是一种对我们很有效的解决方案。毫无疑问还有其他人。

      【讨论】:

        【解决方案4】:

        好吧,没有陈述怎么样?你可能想研究一个 ORM 来为你处理这个......

        【讨论】:

          【解决方案5】:

          一些数据库有专门做这个的专有扩展。

          我同意 INSERT 和 UPDATE 的语法可以更加一致,但这只是现在的现实——它现在不会改变。对于许多场景,最好的选择是您的“全新方式”:使用对象关系映射库(甚至是像 .NET DataSets 这样的弱茶层)来抽象出差异,而不必担心低级 SQL句法。当然,对于每个应用程序来说,这不是一个可行的选择,但它只允许您构造或更新对象、调用 Save 方法并让库为您找出 SQL 语法。

          【讨论】:

            【解决方案6】:

            如果你仔细想想,INSERT 和 UPDATE 是完全一样的。它们将字段名称映射到值,但 UPDATE 具有过滤器。 通过创建一个关联数组,其中键是字段名称,值是您要分配给该字段的值,您就有了映射。您只需根据 INSERT 或 UPDATE 将其转换为正确的字符串格式。 您只需要创建一个函数来根据给定的参数处理转换。

            【讨论】:

              【解决方案7】:

              SQL Server 2008:

              MERGE dbo.MyTable AS T
              USING
               (SELECT  
                @mykey AS MyKey
                @myval AS MyVal
                ) AS S
              
              ON (T.MyKey = S.MyKey)
              
              WHEN MATCHED THEN 
                UPDATE  SET 
                  T.MyVal = S.MyVal
              WHEN NOT MATCHED THEN
                INSERT (MyKey, MyVal)
                VALUES (S.MyKey, S.MyVal)
              

              MySQL:

              INSERT (MyKey, MyVal)
              INTO MyTable
              VALUES({$myKey}, {$myVal})
              ON DUPLICATE KEY UPDATE myVal = {$myVal}
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2013-04-26
                • 2016-02-15
                • 1970-01-01
                • 2022-01-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-02-12
                相关资源
                最近更新 更多