2009-10-19 20 views
12

Birçok kullanıcı içeren tek bir tablom var. Bu tabloda her bir kişi için ayrı ayrı artış yapmak istediğim user_id (INT) adında bir sütuna sahibim. user_id 1MySql INSERT MAX ile sorun() + 1

azından ben hazırladım basit bir örnek başlatmak GEREKİR:

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     | 
+--------------+-----------------------+ 

aşağıdaki sorgu yapacak, ancak 'Bob' zaten tabloda varsa bu sadece ...

çalışacak
INSERT INTO users(user_id, name) SELECT(SELECT MAX(user_id)+1 from users where 
name='Bob'), 'Bob'; 

Bob yoksa (ilk giriş) user_id 0 (sıfır) olarak ayarlanır. Sorun bu. 1 0'dan başlamak için user_id öğesine ihtiyacım var

cevap

16

Böyle bir şey kullanabilirsiniz::

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

Ama böyle sorgu bir yarış duruma yol açabilir

+2

Bu işe yarar! TEŞEKKÜR EDERİM! – Chad

+2

Evet, sorgu çalışır, ancak lütfen ikinci bölümü göz ardı etmeyin . :) Ya da görmezden gelmeye karar verirseniz, en azından bir isim (user_id) 'te benzersiz bir indeks yaratın, böylece bir çoğaltmayı üretecek sorgu başarısız olur. –

+0

Tha Aslında bir sonraki sorum oldu, burada: http://stackoverflow.com/questions/1590648/mysql-innodb-locking-only-the-affected-rows – Chad

1

MAX() + 1 kullanmayın. Tabloda bir otomatik numaralandırma şeması kullanın.

Soruyu düzgün okumadım. Greg'in IFNULL() önerisini kullanın.

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

Will değil masa numarasına otomatik numaralandırma şeması her kayıt ardışık yerine ilk "Bob" 1 ve ikinci "Bob" 2 yapmak yerine, ve ilk "Çad" 1 ve sonra ikinci "Çad" 2 ve benzeri? –

+1

Soruyu düzgün okumadım. Greg'in cevapını IFNULL() ile erteleyeceğim. –

6

Sen IFNULL kullanabilirsiniz. Bir işlemde olduğunuzdan emin olun ve çalıştırmadan önce kullanıcı masasını kilitlersiniz. Aksi takdirde aynı numaraya sahip iki Bobs ile bitirebilirsiniz.

+1

işe yarayacak gibi görünüyor ama bir nedenden dolayı mysql bir sözdizimi hatası veriyor: ... 'SELECT MAX (user_id) +1 adının yanında ad =' Bob '), 1),' Bob '' yakınında kullanmak için sözdizimi satır 1 – Chad

+0

@Chad: Değiştirin IFNULL ('ile' IFNULL (('ve çalışır, sadece dengesiz parantezler. –

+1

Evet, işte bu yüzden işe yaramadı. Merak ediyorum hangi yöntem daha hızlı/en iyi. – Chad

3

reported as a bug in MySQL geçti.

Ben Guilhem BICHOT alıntı yapıyorum:

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;