2011-10-09 16 views
15

Estoy usando un MySQL GUI para migrar algunos sitios a una nueva versión de un CMS seleccionando ciertas tablas y ejecutando la instrucción INSERT generada desde un volcado de respaldo en una tabla vacía (el nuevo esquema). Hay algunas columnas en las tablas antiguas que no existen en la nueva, por lo que la secuencia de comandos se detiene con un error como este:¿Hay alguna forma de ignorar las columnas que no existen en INSERTAR?

línea de comandos: 1 columna Desconocido 'user_id' en 'lista de campos'

Seleccionar con precisión las columnas deseadas para exportar, o editar el archivo de volcado sería demasiado tedioso y lento. Para evitar esto, estoy creando las columnas no utilizadas a medida que se generan los errores, importando los datos ejecutando la consulta, y luego soltando las columnas que no se utilizaron cuando terminé con esa tabla. Miré INSERT IGNORE, pero esto parece ser por ignorar llaves duplicadas (no es lo que estoy buscando).

¿Hay alguna forma de preformar un INSERT ignorando las columnas que no existen en la tabla de destino? Estoy buscando algo "sin problemas", como algunas funcionalidades SQL existentes.

Para aclarar, estoy trabajando con varios archivos de respaldo e importando los datos a una base de datos local para probarlos antes de moverlos al servidor en vivo. Ejemplo del tipo de solución que estoy esperando:

-- Don't try to insert data from columns that don't exist in "new_table" 
INSERT INTO `new_table` {IGNORE UNKNOWN COLUMNS} (`id`, `col1`, `col2`) VALUES 
    (1, '', ''), 
    (2, '', ''); 

Si algo como esto simplemente no existe, estoy feliz de aceptar eso como una respuesta y seguir usando mi solución actual.

+1

Si la lista de campos menciona columnas que no existen, es posible que contenga columnas que coincidan accidentalmente. Por lo que usted sabe, puede ser que el nombre de la tabla sea incorrecto, por lo que accidentalmente inserta datos no válidos en la tabla incorrecta. Esta es una muy mala idea. Si la inserta mal, deje que falle. – GolezTrol

+0

Hay muchas consultas que son peligrosas si se usan incorrectamente o "accidentalmente", no veo por qué esto sería una excepción. –

+0

Claro, pero tener columnas inexistentes en la consulta sugiere un error directo y fallará. INSERT no es una excepción. Una consulta SELECT también falla. – GolezTrol

Respuesta

5

Su técnica actual parece bastante práctica. Solo un pequeño cambio.

En lugar de esperar el error y crear columnas una por una, puede exportar el esquema, hacer una diferencia y descubrir todas las columnas faltantes en todas las tablas.

De esa manera sería menos trabajo.

Su interfaz gráfica de usuario será capaz de exportar solo el esquema o el siguiente cambio en mysqldump será útil para encontrar todas las columnas faltantes.

mysqldump --no-data -uuser -ppassword --database dbname1 > dbdump1.sql 
mysqldump --no-data -uuser -ppassword --database dbname2 > dbdump2.sql 

Diferenciando la dbdump1.sql y dbdump2.sql le dará todas las diferencias en las bases de datos.

+0

Buena adición, definitivamente útil al migrar de un esquema de base de datos a uno diferente. +50 por eso. – Kaivosukeltaja

3

puede escribir una función de almacenamiento de esa manera:

sf_getcolumns(table_name varchar(100)) 

cadena de retorno contatining la lista presentada de esta manera: 'field_1, field_2, field_3, ...'

continuación, crear un procedimiento almacenado

sp_migrite (IN src_db varchar(50), IN target_db varchar(50)) 

que corre trugh las tablas y para cada mesa recibe las listas presentadas y luego crea una cadena como

cmd = 'insert into ' || <target_db><table_name> '(' || <fileds_list> || ') SELECT' || <fileds_list> || ' FROM ' <src_db><table_name> 

ejecutar la cadena para cada tabla

+1

Debo admitir que no estoy seguro de lo que esto significa, pero parece más problemático de lo que vale. Supongo que esperaba una palabra clave o algo que pueda agregar al script existente 'INSERT' que simplemente ignoraría las columnas desconocidas, ya que ya tengo una solución propia. Veré si puedo darle sentido a esto y darle una oportunidad, gracias. Estoy trabajando con archivos de copia de seguridad existentes, por lo que no estoy muy seguro de que esto es lo que estoy buscando. –

+0

Veo que esto tiene voto, por lo que considero que esta no es una mala solución (incluso si mi capacidad limitada de sql no puede comprenderlo todavía). ¿Debo asumir a partir de esta respuesta que lo que estoy buscando específicamente * no * realmente existe? –

+2

@WesleyMurch - sí. En realidad, es una idea ** TERRIBLE ** que el motor maneje la alineación errónea del campo por usted. Indica que no sabes lo que estás insertando, que es un problema importante. – JNK

0

dbForge Studio for MySQL le dará la oportunidad de compare and synchronize datos entre dos bases de datos.

Por defecto, la comparación de datos se realiza solo para los objetos con los mismos nombres; puede usar mapeo automático u objetos de base de datos de mapa manualmente. dbForge Studio le permite personalizar el mapeo de tablas y columnas, para que pueda comparar datos de objetos con nombres, propietarios y estructura que no son iguales. También puede asignar columnas con diferentes tipos, sin embargo, esto puede ocasionar truncamiento, redondeo y errores durante la sincronización de ciertos tipos.

0

encontró su pregunta interesante.

Sabía que había una manera de seleccionar los nombres de columna de una tabla en MySQL; es show columns from tablename. Lo que había olvidado era que todos los datos de la tabla MySQL se guardan en una base de datos especial, llamada "information_schema".

Ésta es la solución lógica, pero no funciona:

mysql> insert into NEW_TABLE (select column_name from information_schema.columns where table_name='NEW_TABLE') values ... 

voy a seguir buscando, sin embargo. Si es posible obtener un valor delimitado por comas de la consulta select column_name, es posible que esté en el negocio.

Editar:

Usted puede utilizar el comando select ... from ... into para generar una sola línea de CSV, como la siguiente:

mysql> select column_name from information_schema.columns where table_name='NEW_TABLE' into outfile 'my_file' fields terminated by '' lines terminated by ', ' 

No sé cómo conseguir esto para dar salida a la CLI MySQL stdout, sin embargo.

1

¿Hay alguna forma de preformar un INSERT ignorando las columnas que no existen en la tabla de destino? Estoy buscando algo "sin problemas", como algunas funcionalidades SQL existentes.

No, no hay una forma "indolora" de hacerlo.

En su lugar, debe manejar explícitamente las columnas que no existen en las tablas finales. Por ejemplo, debe eliminarlos de la secuencia de entrada, soltarlos después del hecho, jugar trucos sucios (engine=BLACKHOLE + desencadenadores para INSERTAR solo lo que desea al esquema de destino verdadero), lo que sea.

Ahora, esto no necesariamente tiene que ser manual - hay herramientas (como Devart noted) y formas de consultar el catálogo de db para determinar los nombres de columna. Sin embargo, no es tan fácil como anotar sus declaraciones INSERT.

¿Tal vez el proveedor de CMS puede proporcionar un script de migración razonable?

+0

Gracias por la respuesta directa, desafortunadamente soy el vendedor de CMS :) Tengo un sistema de migración para las últimas versiones, pero estaba tratando de generar rápidamente actualizaciones de una versión mucho más antigua. –

0

Leo detenidamente todas estas publicaciones porque tengo el mismo desafío. Revise mi solución:

Lo hice en C# pero puede hacerlo en cualquier idioma.

Compruebe la instrucción de inserción para los nombres de columna. Si falta alguno en su tabla actual, AGREGALOS como una columna TEXTO porque TEXTO puede comer cualquier cosa.

Cuando termine de insertar en esa tabla, quite las columnas agregadas.

Listo.

Cuestiones relacionadas