¿Cómo se manejan las claves de aumento automático en INSERT (SELECT * FROM ...)


12

Tengo table1y table2en MySQL. Ambos tienen una auto_incrementclave primaria id.

Si los esquemas de la tabla coinciden y hago INSERT INTO table1 (SELECT * FROM table2)lo que sucede con respecto a las nuevas filas insertadas en table1? ¿Mantienen sus viejos idvalores y generan conflictos cuando una fila de table1tiene el mismo id? ¿Los nuevos valores son generados por auto_increment? ¿Depende del motor de almacenamiento o el bloqueo?

Respuestas:


13

Puede insertar en una columna de incremento automático y especificar un valor. Esto esta bien; simplemente anula el generador de incremento automático.

Si intenta insertar un valor de NULL o 0 o DEFAULT, o si omite la columna de incremento automático de las columnas en su instrucción INSERT, esto activa el generador de incremento automático.

Entonces, está bien INSERT INTO table1 SELECT * FROM table2(por cierto, no necesitas los paréntesis). Esto significa que los valores de ID en table2serán copiados textualmente, y table1serán no generar nuevos valores.

Si desea table1 generar nuevos valores, no puede hacerlo SELECT *. O usa nulo o 0 para la columna de identificación:

INSERT INTO table1 SELECT 0, col1, col2, col3, ... FROM table2;

O bien, omite la columna de la lista de columnas de la instrucción INSERT y de la lista de selección de la instrucción SELECT:

-- No id in either case:
INSERT INTO table1 (col1, col2, col3) SELECT col1, col2, col3, ... FROM table2;

Antes de preguntar, no hay sintaxis en SQL para "select * excepto para una columna". Debe deletrear la lista completa de nombres de columnas que desea insertar.


¿No hay una opción que permita / no permita la inserción de 0 como valor? (Con respecto a su segundo párrafo)
Sascha Rambeaud

1
Sí, SQL_MODE = NO_AUTO_VALUE_ON_ZERO , de lo contrario nunca podríamos insertar un valor cero literal en una columna AI. Si usa este modo SQL, NULL aún funciona para activar el generador de IA, o la omisión de la columna también funciona.
Bill Karwin

@BillKarwin, Respecto a su último párrafo, después de obtener el resultado secundario select * from table, ¿no hay forma de operar en este resultado secundario para eliminar su primera columna?
Pacerier

@Pacerier, si entiendo correctamente, me preguntas si select *puede significar select * except for the first column. La respuesta es no. select *siempre solicita todas las columnas de esa tabla. Si desea un subconjunto, debe deletrear las columnas que desee.
Bill Karwin

@BillKarwin, Hmm, estaba pensando en girar la tabla para hacer cláusulas verticales, luego girarla hacia atrás, por ejemplo, select*from transpose(select*from(transpose(select*from table where Id=1))where col_name<>Id)o tal vez de manera más sucinta select*from table where Id=1 and $col<>Id, ¿qué te parece?
Pacerier

3

La identificación de la selección será el mismo valor insertado en la tabla. Esto provocará un error si está intentando duplicar filas existentes.

Bill Karwin: Antes de preguntar, no hay sintaxis en SQL para "select * excepto para una columna".

Esto se puede lograr con algo de creatividad:

SET @sql = CONCAT('INSERT INTO <table> SELECT null, 
    ', (SELECT GROUP_CONCAT(COLUMN_NAME) 
    FROM information_schema.columns 
    WHERE table_schema = '<database>' 
    AND table_name = '<table>' 
    AND column_name NOT IN ('id')), ' 
from <table> WHERE id = <id>');  

PREPARE stmt1 FROM @sql;
EXECUTE stmt1;

Esto dará como resultado que la nueva fila obtenga una identificación con incremento automático en lugar de la identificación de la fila seleccionada.


2
Inteligente, pero para mí, eso cuenta como deletrear la lista completa de los nombres de columna que desea insertar.
Bill Karwin

1
Bueno, es mysql automáticamente deletreando en lugar de hacerlo manualmente. Si tiene tablas con muchas columnas, evitará que se pierda una o que escriba algunas mal.
curmil
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.