2009-10-19 196 views
12

我有一個包含許多用戶的表。在那張表中,我有一個名爲user_id(INT)的列,我想爲每個人單獨增加。 USER_ID必須從1開始問題與MySql INSERT MAX()+ 1

我已經準備了一個簡單的例子:

Showing all names 
+--------------+-----------------------+ 
| user_id  | name     | 
+--------------+-----------------------+ 
| 1   | Bob     | 
| 1   | Marry     | 
| 2   | Bob     | 
| 1   | John     | 
| 3   | Bob     | 
| 2   | Marry     | 
+--------------+-----------------------+ 


Showing only where name = Bob 
+--------------+-----------------------+ 
| user_id  | name     | 
+--------------+-----------------------+ 
| 1   | Bob     | 
| 2   | Bob     | 
| 3   | Bob     | 
+--------------+-----------------------+ 

下面的查詢將做到這一點,但如果「鮑勃」表中已經存在,它只會工作...

INSERT INTO users(user_id, name) SELECT(SELECT MAX(user_id)+1 from users where 
name='Bob'), 'Bob'; 

如果Bob不存在(第一項)user_id設置爲0(零)。這就是問題。我需要user_id從1開始而不是0.

回答

16

您可以使用這樣的事情:

INSERT INTO users (user_id, name) 
SELECT 1 + coalesce((SELECT max(user_id) FROM users WHERE name='Bob'), 0), 'Bob'; 

但是這樣的查詢可能導致競爭條件。確保您處於事務中,並在運行之前鎖定用戶表。否則,最終可能會有兩個相同編號的Bob。

+2

This Works!THANK YOU! – Chad 2009-10-19 08:58:53

+2

是的,查詢工作,但請不要忽略第二部分。:)或者如果你決定忽略它,至少在'(name,user_id)'上創建一個唯一索引,這樣否則會產生重複的查詢將失敗。 – 2009-10-19 11:54:46

+0

t實際上是我的下一個問題,它在這裏:http://stackoverflow.com/questions/1590648/mysql-innodb-locking-only-the-affected-rows – Chad 2009-10-19 19:41:22

1

請勿使用MAX()+ 1。在桌上使用自動編號方案。

我沒有正確地閱讀這個問題。使用Greg的建議IFNULL()。

+2

不會對錶號自動編號方案的每個記錄順序,而不是使第一「鮑勃」 1,第二個「鮑勃」 2,和第一個「乍得」1,然後第二個「乍得」2等? – 2009-10-19 08:43:28

+1

我沒有正確閱讀這個問題。我會按照IFNULL()的格式回答Greg的問題。 – 2009-10-19 08:48:14

6

您可以使用IFNULL

INSERT INTO users(user_id, name) 
SELECT(IFNULL((SELECT MAX(user_id)+1 from users where name='Bob'), 1), 'Bob'; 
+1

看起來像它會工作,但由於某種原因,mysql會拋出一個語法錯誤: ...在用戶附近使用'SELECT MAX(user_id)+1'時使用的語法,其中name ='Bob'),1),'Bob''在第1行 – Chad 2009-10-19 08:57:20

+0

@Chad:用'IFNULL替換'IFNULL((''並且它可以工作,它只是不平衡的括號) – 2009-10-19 09:02:14

+1

是的,這就是爲什麼它不起作用,我不知道哪種方法更快/最好。 – Chad 2009-10-19 09:08:52

3

這是reported as a bug in MySQL

我引述吉揚Bichot:

Second, here is the simplest of workarounds:
instead of using:
insert into foo(lfd) values((select max(lfd) from foo)+1)
just do
insert into foo(lfd) select (max(lfd)+1) from foo;