2011-02-18 87 views
38

Estoy interesado en exportar un subconjunto de valores de una base de datos MySQL a un archivo con formato JSON en el disco.¿Cómo exportar una base de datos MySQL a JSON?

He encontrado un enlace que habla de una posible manera de hacer esto: http://www.thomasfrank.se/mysql_to_json.html

... pero cuando se utiliza el método de esa página, parece que funciona pero con dos problemas:

1) Solo devuelve alrededor de 15 resultados, y el último se interrumpe abruptamente (incompleto). Mi consulta estándar para este regresa alrededor de 4000 resultados cuando lo ejecutas como SELECT name, email FROM students WHERE enrolled IS NULL Pero cuando corro como:

SELECT 
    CONCAT("[", 
      GROUP_CONCAT(
       CONCAT("{name:'",name,"'"), 
       CONCAT(",email:'",email,"'}") 
     ) 
    ,"]") 
AS json FROM students WHERE enrolled IS NULL; 

... como se describe en el enlace, sólo se devuelve (como he mencionado) 15 resultados . (fwiw, verifiqué estos resultados contra los 4000 que se supone que tengo, y estos 15 son los mismos que los primeros 15 de los 4000)

2) Parece que hay caracteres de "escape" incluidos en el archivo real cuando agregue INTO OUTFILE '/path/to/jsonoutput.txt' FIELDS TERMINATED BY ',' al final de esa consulta. Así que las comas terminan pareciendo '\,' cuando obviamente me gustaría tener las comas sin el \.

¿Alguna idea sobre cómo obtener una salida JSON adecuada de MySQL? (¿Ya sea usando este método, o algún otro método)?

Gracias!

+1

Para una solución basada en shell, puede ejecutar su consulta y generar json usando [jo] (https://github.com/jpmens/jo), o puede canalizar su salida de consulta a [export-mysql-to-json] (https://github.com/Sufi-Al-Hussaini/export-mysql-to-json). –

Respuesta

15

Puede estar pidiendo demasiado a MySQL que espere que produzca json bien formado directamente de una consulta. En su lugar, considere producir algo más conveniente, como CSV (utilizando el fragmento INTO OUTFILE '/path/to/output.csv' FIELDS TERMINATED BY ',' que ya conoce) y luego transformar los resultados en json en un lenguaje con soporte integrado, como python o php.

Editar ejemplo pitón, usando la multa SQLAlchemy:

class Student(object): 
    '''The model, a plain, ol python class''' 
    def __init__(self, name, email, enrolled): 
     self.name = name 
     self.email = email 
     self.enrolled = enrolled 

    def __repr__(self): 
     return "<Student(%r, %r)>" % (self.name, self.email) 

    def make_dict(self): 
     return {'name': self.name, 'email': self.email} 



import sqlalchemy 
metadata = sqlalchemy.MetaData() 
students_table = sqlalchemy.Table('students', metadata, 
     sqlalchemy.Column('id', sqlalchemy.Integer, primary_key=True), 
     sqlalchemy.Column('name', sqlalchemy.String(100)), 
     sqlalchemy.Column('email', sqlalchemy.String(100)), 
     sqlalchemy.Column('enrolled', sqlalchemy.Date) 
    ) 

# connect the database. substitute the needed values. 
engine = sqlalchemy.create_engine('mysql://user:[email protected]/database') 

# if needed, create the table: 
metadata.create_all(engine) 

# map the model to the table 
import sqlalchemy.orm 
sqlalchemy.orm.mapper(Student, students_table) 

# now you can issue queries against the database using the mapping: 
non_students = engine.query(Student).filter_by(enrolled=None) 

# and lets make some json out of it: 
import json 
non_students_dicts = (student.make_dict() for student in non_students) 
students_json = json.dumps(non_students_dicts) 
+0

¡Impresionante, muchas gracias! Terminé siguiendo tus consejos antes de la edición, y tengo un script de python en funcionamiento que se lee en el archivo CSV y se convierte en JSON, como me recomendó :) Pero definitivamente he querido echarle un vistazo a SQLAlchemy, así que esta edición también es una ¡gran ayuda! ¡¡¡Gracias!!! – mindthief

7

esto es somthing que se debe hacer en la capa de aplicación.

Por ejemplo, en php que es un muy sencillo como

Editar Agregado el material de conexión db. No se necesita nada externo.

$sql = "select ..."; 
$db = new PDO ("mysql:$dbname", $user, $password) ; 
$stmt = $db->prepare($sql); 
$stmt->execute(); 
$result = $stmt->fetchAll(); 

file_put_contents("output.txt", json_encode($result)); 
+0

Nunca he usado php, pero se ve muy bien. ¿Necesito crear una conexión con la base de datos? ¿Requiere eso una biblioteca externa? Tuve un montón de tiempo tratando de obtener MySQLdb trabajando para Python ... (no funcionó eventualmente: \\) – mindthief

+1

+1 Creo que necesita '$ stmt -> execute();' también antes de 'fetchAll() '. – goyalankit

+0

no pudo hacer que esto funcione, teniendo en cuenta que se anuncia como "tan simple como ..." Esperaba que simplemente funcionara, pero no es así. Tal vez hay un poco más de explicación requerida. Me resultó mucho más fácil seguir la otra publicación sobre el uso de ruby ​​y mysql2xxxx, ¡lo cual realmente funcionó! –

34

Si tiene Rubí, puede instalar la gema mysql2xxxx (no la gema mysql2json, que es una joya diferente):

$ gem install mysql2xxxx 

y luego ejecutar el comando

$ mysql2json --user=root --password=password --database=database_name --execute "select * from mytable" >mytable.json 

La gema también proporciona mysql2csv y mysql2xml. No es tan rápido como mysqldump, pero también no sufre de algunos de weirdnesses de mysqldump (como sólo ser capaz de volcar CSV desde el mismo equipo que el servidor MySQL en sí)

+1

parece que --username = root ahora es --user = root en la nueva versión y es posible que deba proporcionar un nombre de base de datos con --database = somedatabase – iouri

+0

mysqldump no tiene que ejecutarse en el mismo servidor afaik .. ¿A menos que sea específico para la salida de CSV? – gatoatigrado

2

como se describe en el enlace, sólo regresa (como mencioné) 15 resultados.(Fwiw, he comprobado estos resultados en relación con el 4000 se supone que debo conseguir, y éstas 15 son los mismos que los primeros 15 del 4000)

Eso es porque mysql restringe la longitud de los datos devueltos por concat grupo al valor establecido en @@ group_concat_max_len tan pronto como llegue a esa cantidad trunca y devuelve lo que ha obtenido hasta ahora.

Puede establecer @@ group_concat_max_len de diferentes formas. referencia The mysql documentation...

+0

ah bien, es bueno saberlo, gracias! – mindthief

1

Además, si está exportando en la capa de aplicación, no olvide limitar los resultados. Por ejemplo, si tiene filas de 10M, debe obtener resultados parte por parte.

6

Otra solución, si está utilizando Ruby, es escribir un script de conexión a la base de datos con ActiveRecord. Usted tendrá que instalar primero

joya instalar activerecord

# ruby ./export-mysql.rb 
require 'rubygems' 
require 'active_record' 

ActiveRecord::Base.establish_connection(
    :adapter => "mysql", 
    :database => "database_name", 
    :username => "root", 
    :password => "", 
    :host => "localhost" 
) 

class Event < ActiveRecord::Base; end 
class Person < ActiveRecord::Base; end 

File.open("events.json", "w") { |f| f.write Event.all.to_json } 
File.open("people.json", "w") { |f| f.write Person.all.to_json } 

También puede agregar métodos a las clases ActiveRecord si se quiere manipular datos en primer lugar o incluir o excluir ciertas columnas.

Person.all.to_json(:only => [ :id, :name ]) 

Con ActiveRecord no se limita a JSON. Puede exportar tan fácilmente como XML o YAML

Person.all.to_xml 
Person.all.to_yaml 

Usted no está limitado a MySQL. Cualquier base de datos compatible con ActiveRecord (Postgres, SQLite3, Oracle ... etc.).

Y vale la pena mencionar que podría abrir otro mango a una base de datos

require 'active_record' 

ActiveRecord::Base.configurations["mysql"] = { 
    :adapter => 'mysql', 
    :database => 'database_name', 
    :username => 'root', 
    :password => '', 
    :host  => 'localhost' 
} 


ActiveRecord::Base.configurations["sqlite3"] = { 
    :adapter => 'sqlite3', 
    :database => 'db/development.sqlite3' 
} 

class PersonMySQL < ActiveRecord::Base 
    establish_connection "mysql" 
end 

class PersonSQLite < ActiveRecord::Base 
    establish_connection "sqlite3" 
end 


PersonMySQL.all.each do |person| 
    PersonSQLite.create(person.attributes.except("id")) 
end 

Aquí es un poco de blog rápida sobre ello http://www.seanbehan.com/how-to-export-a-mysql-database-to-json-csv-and-xml-with-ruby-and-the-activerecord-gem

+0

Excelente hombre! Muy bien explicado y me encanta la técnica de conectarme a múltiples bases de datos. – Saim

+0

La creación de instancias de objetos agregará mucha sobrecarga al trabajar con millones de registros. –

1

Puede exportar cualquier consulta SQL en JSON directamente desde phpMyAdmin

+0

gracias! no pensé en eso. – oak

+1

Más detalles por favor! No puedo encontrar esta opción en ningún lado. – a20

5

Sé que esto es viejo, pero por el bien de alguien que busca una respuesta ...

There's a JSON library for MYSQL that can be found here Necesita tener acceso de root a su servidor y sentirse cómodo instalando complementos (es simple).

1) cargar el lib_mysqludf_json.so en el directorio de plugins de la instalación de MySQL

2) ejecute el archivo lib_mysqludf_json.sql (que prácticamente hace todo el trabajo por usted. Si se encuentra con problemas sólo eliminar cualquier cosa que empieza con 'DROP FUNCTION ...')

3) codificar su consulta en algo como esto:

SELECT json_array(
     group_concat(json_object(name, email)) 
FROM .... 
WHERE ... 

y ha de devolver algo así como

[ 
    { 
    "name": "something", 
    "email": "[email protected]" 
    }, 
    { 
    "name": "someone", 
    "email": "[email protected]" 
    } 

] 
0

utilizar el siguiente código de rubí

require 'mysql2' 

client = Mysql2::Client.new(
    :host => 'your_host', `enter code here` 
    :database => 'your_database', 
    :username => 'your_username', 
    :password => 'your_password') 
table_sql = "show tables" 
tables = client.query(table_sql, :as => :array) 

open('_output.json', 'a') { |f|  
    tables.each do |table| 
     sql = "select * from `#{table.first}`" 
     res = client.query(sql, :as => :json) 
     f.puts res.to_a.join(",") + "\n" 
    end 
} 
7

Otra posibilidad es usar el MySQL Workbench.

Hay una opción de exportación JSON en el menú contextual del navegador de objetos y en el menú de cuadrícula de resultados.

Más información sobre MySQL documentation: Data export and import.

6

HeidiSQL le permite hacer esto también.

Resalte cualquier dato en la pestaña DATOS, o en el conjunto de resultados de la consulta ... luego haga clic derecho y seleccione la opción Exportar filas de cuadrícula. Esta opción permite entonces puede exportar cualquiera de sus datos como JSON, directamente en el portapapeles o directamente en el archivo:

enter image description here

+0

Me encantó de esta manera. – Nere

0

Para cualquier persona que quiera hacer esto usando Python, y ser capaz de exportar todas las tablas sin predefinining nombres de campo, etc., escribí un guión corto para esto el otro día, espero que alguien le resulta útil:

from contextlib import closing 
from datetime import datetime 
import json 
import MySQLdb 
DB_NAME = 'x' 
DB_USER = 'y' 
DB_PASS = 'z' 

def get_tables(cursor): 
    cursor.execute('SHOW tables') 
    return [r[0] for r in cursor.fetchall()] 

def get_rows_as_dicts(cursor, table): 
    cursor.execute('select * from {}'.format(table)) 
    columns = [d[0] for d in cursor.description] 
    return [dict(zip(columns, row)) for row in cursor.fetchall()] 

def dump_date(thing): 
    if isinstance(thing, datetime): 
     return thing.isoformat() 
    return str(thing) 


with closing(MySQLdb.connect(user=DB_USER, passwd=DB_PASS, db=DB_NAME)) as conn, closing(conn.cursor()) as cursor: 
    dump = {} 
    for table in get_tables(cursor): 
     dump[table] = get_rows_as_dicts(cursor, table) 
    print(json.dumps(dump, default=dump_date, indent=2)) 
0

esto podría ser un nicho más respuesta, pero si usted está en windows y MySQL Workbench sólo se puede seleccionar el tabla que desee y haga clic en Exportar/Importar en la cuadrícula de resultados. Esto le dará varias opciones de formato, incluyendo .json

Cuestiones relacionadas