【问题标题】:mySQL/PHP to update if the row exists or else insert when column to check is not uniquemySQL/PHP 如果行存在则更新,否则在要检查的列不唯一时插入
【发布时间】:2010-12-05 12:58:39
【问题描述】:

我已阅读有关 REPLACE 和 INSERT ON DUPLICATE 键查询的信息,虽然我可以看到它们有多么有用,但它们似乎不适用于我的目的。也许我的数据库设计偏离了它应有的样子,但无论哪种方式,我都希望我能做到这一点。

我正在尝试模拟一个在线商店来自学 mysql 和 php,并且我正在记录一个会话 id,用于将个人的购物车拉回以进行个人访问,并尝试将库存写入我所在的购物车有一个问题是试图检查该项目是否在购物车中。我希望每个用户的每个项目都是唯一的,但它不应该对整个表都是唯一的,否则这会阻止多个用户购买相同的项目,不是吗?

到目前为止,我的桌子是这样的:

 | Cart ID(key) | USER_ID(fk) | ItemNum | ItemQTY |

我基本上想看看 USER_ID 在他们的购物车中是否已经有 > 0 ItemQTY 的 ItemNum。如果他们这样做,我希望 itemQTY 更新为 itemQTY + 无论他们添加多少,如果没有,则插入一个新行。

为了做到这一点,我必须在写作之前进行查询吗?

【问题讨论】:

    标签: php mysql insert replace


    【解决方案1】:

    您可以编写一个存储过程并使用该存储过程来处理插入。

    您将需要了解如何编写存储过程并从 PHP 执行它们。

    此外,在存储过程中,您将需要执行多个查询,但对于您的应用程序来说,它看起来像是对过程的一次调用。

    HTH。

    【讨论】:

    • 将用户输入添加到存储过程是否安全,就像将其添加到参数化查询一样?
    • 我不知道。不安全吗?是否在存储过程中声明输入变量类型?如果您确实声明了类型但尝试传入错误的类型怎么办?发生什么了?您是否甚至在执行任何查询之前都没有验证输入?是否有任何mysql php库支持存储过程的参数绑定?
    【解决方案2】:

    对于初学者...我认为只运行查询以检查它是否存在可能是可以的。然后,当您通常更熟悉 php 和 mysql 时,开始构建您的知识。

    其他人可能不同意,但在学习新语言时,我喜欢在让它们“完美”之前先让它们发挥作用。

    【讨论】:

    • 最终,即使在生产系统上,如果发现自己怀疑运行快速查询然后插入或更新真的会杀死我的数据库服务器,而不是广受欢迎的网站(如果我'我错了)。我可能会这样做,但我认为至少了解一下专业人士的做法是很有价值的。
    • “天哪,多花了 0.00023 秒!” :)
    • 执行两个查询甚至可能比单个插入更快,因为读取将启动更新。要更新的块已经在各种缓存中。
    【解决方案3】:

    我认为您需要 CartID 和 ItemNum 上的多列唯一键:

    alter table my_table add unique( CartID, ItemNumber );
    

    那么你可以这样做:

    insert into my_table values( 1, 'joe', 12345, 1 ) on duplicate key update ItemQTY = ItemQTY + 1;
    

    【讨论】:

      【解决方案4】:

      传统的购物车软件为每位用户提供一个购物车,并且每次用户返回时都会恢复该购物车。因为您同时拥有CartIDUserID,所以给人的印象是用户可以拥有多个购物车。

      然而,最好有三个表; Users, Carts & CartItems

      Users 需要UserIDCarts 需要CartID 和类似OwnerID(引用Users.UserID),CartItems 需要CartID(引用Carts.CartID), ItemIDQuantity

      您甚至可以变得更简单,因为用户永远只有一个购物车,您可以完全忽略购物车表并将CartItems.CartID 替换为CartItems.OwnerID(引用Users.UserID

      我希望这会有所帮助。

      【讨论】:

      • 这是我最初的直觉......我的 cardID 老实说是一个多余的值,因为我的印象是所有表都应该有一个唯一的主键。我不确定我从哪里得到印象,但在我看来,您是说表不需要唯一的主键并且可以只使用一个伪造的键?
      • 外键需要一个唯一索引,因此它服务于主键的语义目的。然而,innodb 将创建一个隐藏的自动递增键来对磁盘上的数据进行排序。因此,有人建议创建代理主键。如果您想将有关关系的其他信息存储在另一个表中,这也很有用。
      • 或者如果您想允许用户保存多个购物车或将购物车发送给其他用户。
      • 如果它们之间存在外键关系,您绝对不想做的一件事是调用一个表中的 UserID 列和另一个表中的 OwnerID。语义上,键关系的性质使两个值在它们相同时是等效的,这意味着您通过用不同的名称标识同一事物而造成混淆。将其作为 UserID 保存在 CartItems 表中。更好的是,如果您将 UserID 列保留在 CartItems 表之外并且在 Carts 表中具有外键,您的设计将会更加灵活。
      • RibaldEddie,OwnerID 是对的;它确实应该是所有表中的 UserID 以避免混淆。但是,如果您希望拥有Carts 表,我宁愿将UserID 保留在Carts 中,而不是将CartID 保留为Users,因为对我来说它说“购物车有用户”而不是到“每个用户都有一个购物车”。各有千秋。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-12
      相关资源
      最近更新 更多