我想知道在这个问题上是否可以减少逻辑重复。假设我有一个 users 表和 email 列,每个记录应该是唯一的。我通常做的是在列上有一个唯一的索引和验证代码来检查值是否已被使用:
users
email
SELECT EXISTS (SELECT * FROM `users` WHERE `email` = 'foo@bar.com')
在尝试输入非唯一值时,跳过显式检查而仅仅依赖数据库错误是否可行?如果我们在两层(数据库和应用程序代码)中重复惟一性逻辑,它就不是真正的干巴巴的。
kpbwa7wx1#
我想你说的“干”是指不要重复你自己。在多个地方应用同样的逻辑并不是本质上的坏事——有句老话“两次测量,一次切割”。在更一般的情况下,我通常遵循应用insert并捕获违反约束的模式,但对于具有电子邮件地址的用户来说,情况要复杂得多。如果您的电子邮件是唯一要求唯一的属性,那么我们可以跳过很多关于一个人拥有多个帐户的讨论,并找出在报告违反约束时哪个属性不是唯一的。电子邮件是唯一的unqiue属性在你的问题中是隐含的,但没有说明。根据您的评论,您似乎正在从php代码发送此sql。鉴于此,首先轮询记录有两个真正的问题:1) 性能和容量:这是对数据库的额外往返、解析和读取操作2) 安全性:让应用程序用户直接访问(特别是对控制访问的表)不利于安全性。将其封装为以定义者权限运行并返回与应用程序逻辑更一致的消息的存储过程/函数更安全。即使您仍然遵循实现poll first/insert if缺席的路线,您也消除了问题1中的大部分开销。你也可以花点时间考虑一下你的查询和。。。
SELECT 1 FROM `users` WHERE `email` = 'foo@bar.com'
9rbhqvlz2#
在数据库中强制电子邮件地址的唯一性是有意义的。只有这样你才能确定它真的是独一无二的。如果只在php代码中执行,那么该代码中的任何错误都可能损坏数据库。这两方面都不需要,但在我看来,这并不违反干法规则。例如,您可能希望在注册新用户时检查电子邮件地址是否存在,而不仅仅依赖于报告错误的数据库。
cpjpxq1n3#
我经常这么做。在我的自定义数据库类中,我为违反的限制抛出了一个特定的异常(这可以很容易地从mysql返回的数字错误代码中推断出来),然后在插入时捕获这样的异常。它的优点是简单,还可以防止竞争,mysql在两种变体中都会处理数据完整性,包括数据本身和并发访问。唯一的缺点是,当您有多个索引时(例如,您可能希望有一个唯一的电子邮件和一个唯一的用户名),很难找出哪个索引失败。mysql驱动程序只在错误消息的文本中报告违反的密钥名,没有特定的api。在任何情况下,您都可能希望在早期阶段将可用名称通知用户,因此预先检查也是有意义的。
brqmpdu14#
在数据库约束之上,您应该在尝试插入之前检查给定的电子邮件是否已经存在于其中。以这种方式处理它更干净,允许更好地验证和响应客户端,而不会抛出错误。经典约束(如min/max)也是如此(请注意,mysql上忽略了此类约束)。在向数据库提交任何更改之前,应该检查、验证并向客户端返回验证错误消息。
4条答案
按热度按时间kpbwa7wx1#
我想你说的“干”是指不要重复你自己。在多个地方应用同样的逻辑并不是本质上的坏事——有句老话“两次测量,一次切割”。
在更一般的情况下,我通常遵循应用insert并捕获违反约束的模式,但对于具有电子邮件地址的用户来说,情况要复杂得多。如果您的电子邮件是唯一要求唯一的属性,那么我们可以跳过很多关于一个人拥有多个帐户的讨论,并找出在报告违反约束时哪个属性不是唯一的。电子邮件是唯一的unqiue属性在你的问题中是隐含的,但没有说明。
根据您的评论,您似乎正在从php代码发送此sql。鉴于此,首先轮询记录有两个真正的问题:
1) 性能和容量:这是对数据库的额外往返、解析和读取操作
2) 安全性:让应用程序用户直接访问(特别是对控制访问的表)不利于安全性。将其封装为以定义者权限运行并返回与应用程序逻辑更一致的消息的存储过程/函数更安全。即使您仍然遵循实现poll first/insert if缺席的路线,您也消除了问题1中的大部分开销。
你也可以花点时间考虑一下你的查询和。。。
9rbhqvlz2#
在数据库中强制电子邮件地址的唯一性是有意义的。只有这样你才能确定它真的是独一无二的。
如果只在php代码中执行,那么该代码中的任何错误都可能损坏数据库。
这两方面都不需要,但在我看来,这并不违反干法规则。例如,您可能希望在注册新用户时检查电子邮件地址是否存在,而不仅仅依赖于报告错误的数据库。
cpjpxq1n3#
我经常这么做。在我的自定义数据库类中,我为违反的限制抛出了一个特定的异常(这可以很容易地从mysql返回的数字错误代码中推断出来),然后在插入时捕获这样的异常。
它的优点是简单,还可以防止竞争,mysql在两种变体中都会处理数据完整性,包括数据本身和并发访问。
唯一的缺点是,当您有多个索引时(例如,您可能希望有一个唯一的电子邮件和一个唯一的用户名),很难找出哪个索引失败。mysql驱动程序只在错误消息的文本中报告违反的密钥名,没有特定的api。
在任何情况下,您都可能希望在早期阶段将可用名称通知用户,因此预先检查也是有意义的。
brqmpdu14#
在数据库约束之上,您应该在尝试插入之前检查给定的电子邮件是否已经存在于其中。以这种方式处理它更干净,允许更好地验证和响应客户端,而不会抛出错误。
经典约束(如min/max)也是如此(请注意,mysql上忽略了此类约束)。在向数据库提交任何更改之前,应该检查、验证并向客户端返回验证错误消息。