2011-04-17 97 views
0

当我在用户表中插入新记录时,首先检查电子邮件和昵称尚未添加。另一个同时注册相同数据的用户有可能是我的错误结果吗?澄清:策略查询执行

连接1:

> SELECT * FROM account WHERE username = 'test'; 

空集(0.00秒)

连接2:

> SELECT * FROM account WHERE username = 'test'; 

空集(0.00秒)

> INSERT INTO account(username) VALUES ('test'); 

查询行,1行受影响(0.01秒)

连接1:

> INSERT INTO account(username) VALUES ('test'); 

错误。重复密钥

我想知道的是,如果MySQL以这种方式工作,通过在查询时运行查询以及使用最佳实践。 我注意到在转换过程中,其他连接所做的更改不可见。为什么?您可以在转换之外使用SELECT ... FOR UPDATE?大量使用外键来确保数据完整性是一种推荐的做法?

编辑: 换句话说。忽略这个愚蠢的例子。我想谁登记下一个用户有一个年龄比所有那些已经

> SELECT MAX (age) FROM account; 

[...检查,如果用户的年龄较高...]

> INSERT INTO accounts (age) VALUES ('$ var'); 

更大怎样确保有两个用户在同一个野外阵营有风险吗?

回答

1

这种情况下的最佳做法是创建UNIQUE约束(UNIQUE INDEX)。

当你同时得到2个查询时,你会得到1个查询失败,并能够处理它与适当的消息给用户。

+0

他已经有一个唯一索引:“*错误重复键*” – 2011-04-17 13:53:47

+0

@ypercube:是的,这是一个最好的做法反正)) – zerkms 2011-04-17 13:58:52

0

列出所有MySQL最佳实践的Gheez需要一本书。

让我先回答:

我想谁注册了一个用户有一个年龄比那些更大的已经

使用触发器:

DELIMITER $$ 

CREATE TRIGGER bi_account_each BEFORE INSERT ON account FOR EACH ROW 
BEGIN 
    declare MaxAge integer; 

    SELECT Max(account.age) INTO MaxAge FROM account; 
    IF (new.age <= MaxAge) THEN BEGIN 
    /* force an error by selecting from a table_that_does_not_exist.*/ 
    SELECT * FROM 
     ErrFromTrigger_bi_account_each_New_Member_Must_Be_Older_then_The_Last 
    END; END IF; 

END$$ 

DELIMITER ; 

或存储的功能

DELIMITER $$ 

CREATE FUNCTION CanInsertInAccount(pAge integer) RETURNS boolean 
BEGIN 
    declare MaxAge integer; 
    declare InsertAllowed boolean; 

    SELECT Max(account.age) INTO MaxAge FROM account; 
    SET InsertAllowed = (pAge > MaxAge); 

    RETURN InsertAllowed; 
END$$ 

DELIMITER ; 

参见:http://dev.mysql.com/doc/refman/5.1/en/triggers.html
有关触发器的更多信息。
和:http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html
有关存储过程和函数的更多信息。

至于的最佳实践,我的名单是:

  1. 不要相信客户输入:当插入从PHP值到MySQL总是使用mysql_real_escape_string()值(或使用PDO {prepared statements});这将保护你免受SQL注入攻击。
  2. 在显示客户输入的数据之前剥离HTML标签禁止所有HTML。使用htmlspecialchars()将HTML字符转换为HTML实体。因此,标记<和>标记标记的开始/结束的字符将变成<和>。仅仅使用strip_tags()仅仅允许一些标签是不够的,因为函数不会去除onclick或onload等有害属性。
  3. 规范化数据库
  4. 使用外键检查
  5. 使用事务,但提交(或回滚)经常可以。只在一次交易中放入属于一起的东西。
  6. 使用触发器
  7. 使用存储过程来操作和测试的东西,取决于你的数据库的布局。

这就是我现在可以想到的,名单并不完整,这些事情都是有些私人的。它适合我,YMMV。