2009-10-19 17 views
12

Tengo una única tabla que contiene muchos usuarios. En esa tabla tengo una columna llamada user_id (INT), que deseo incrementar por separado para cada persona. user_id debe comenzar en 1Problema con MySql INSERT MAX() + 1

He preparado un ejemplo sencillo:

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

La siguiente consulta va a hacer esto, pero sólo funcionará si 'Bob' ya existe en la tabla ...

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

Si Bob no existe (primera entrada) user_id se establece en 0 (cero). Este es el problema. Necesito el user_id para comenzar desde 1 no 0.

Respuesta

16

se puede usar algo como esto:

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

Pero tales consulta puede conducir a una condición de carrera. Asegúrese de estar en una transacción y bloquee la tabla de usuarios antes de ejecutarla. De lo contrario, podría terminar con dos Bobs con el mismo número.

+2

¡Esto funciona! GRACIAS – Chad

+2

Sí, la consulta funciona, pero no ignores la segunda parte . :) O si decide ignorarlo, al menos cree un índice único en '(name, user_id)' para que la consulta que de otro modo produciría un duplicado falle. –

+0

Tha Era mi siguiente pregunta, está aquí: http://stackoverflow.com/questions/1590648/mysql-innodb-locking-only-the-affected-rows – Chad

1

No use MAX() + 1 a continuación. Use un esquema de numeración automática en la mesa.

No he leído la pregunta correctamente. Use la sugerencia de Greg de IFNULL().

+2

voluntad no un esquema de numeración automática en el número de tabla de cada registro de forma secuencial, en lugar de hacer el primer "Bob" 1 y el segundo "Bob" 2, y el primer "Chad" 1 y luego el segundo "Chad" 2 y así sucesivamente? –

+1

No leí la pregunta correctamente. Voy a diferir a la respuesta de Greg con IFNULL(). –

6

Puede utilizar IFNULL:

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

parece que funcionaría pero por alguna razón mysql arroja un error de sintaxis: ... sintaxis para usar cerca de 'SELECT MAX (user_id) +1 de usuarios donde name =' Bob '), 1),' Bob '' en la línea 1 – Chad

+0

@Chad: Reemplazar 'IFNULL (' con 'IFNULL ((' y funcionará, es solo paréntesis desequilibrado . –

+1

Sí, es por eso que no funcionó. Me pregunto qué método es más rápido/mejor. – Chad

3

Ha sido reported as a bug in MySQL.

cito Guilhem 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;