tablas script orientado objetos las incluyendo generar ejemplos datos como sql perl oop

orientado - script de base de datos sql ejemplos



¿Cómo puedo armar SQL con Perl orientado a objetos? (8)

A menos que malinterprete, esto parece una aplicación ETL (Extraer / Transformar / Cargar) que no se ha arreglado para mantener las tres etapas separadas.

Si el modelo de salida es solo una tabla o dos, probablemente estés tan bien usando SQL. De lo contrario, y especialmente si hay relaciones entre las tablas en las que se está insertando, un ORM decente debería simplificar las cosas.

Tomando la idea de los 50 estados, realmente no se puede alejar de tener 50 procesos de "extracción", con suerte con una biblioteca de rutinas compartidas. Atacaría el problema con una fuente de entrada a la vez, refactorizando a medida que añadía nuevas, pero teniendo cuidado de encapsular las partes variables para saber exactamente dónde se deberán hacer los cambios cuando un proveedor cambie su formato.

La parte de "transformación" no debería ser demasiado onerosa: solo toma lo que tienes y prepáralo para la salida.

Actualmente estoy a cargo de un proceso que parece ser muy íntimo con la base de datos. El objetivo de mi programa / script / framework es hacer la uniformidad de fuentes de datos dispares. Usando una forma de inyección de dependencia, mi proceso en un nivel muy alto funciona bien. La implementación de cada tipo de fuente de datos está oculta desde la abstracción empresarial de más alto nivel de lo que está sucediendo. Estupendo. Mis preguntas son dos.

1) Tengo un párrafo largo (y es la longitud que me molesta) que ensambla una declaración SQL en Perl-espacio de cómo traducir estas diferentes fuentes de datos en un formato de final homogéneo. Entonces, la cadena de SQL siempre depende del tipo de datos con los que estoy trabajando. La cláusula WHERE depende, la cláusula FROM depende, la cláusula INSERT depende, todo depende. Es el alto nivel de dependencia lo que me confunde. ¿Cómo modelo este proceso de una manera orientada a objetos? MagicObject-> buildSQL? Eso es esencialmente lo que tengo ahora, pero parece que todas las partes del código saben demasiado, por lo tanto, es largo.

2) Si tengo una función que hace algo (¿crea SQL?), ¿Transfiero los objetos de negocios completos y luego los corono en el último minuto? ¿O los vuelvo a secuenciar antes y solo dejo que mi función maneje lo que necesita, en lugar de renderizar los objetos por sí misma?

Editar : Si bien no dudo de la importancia de los ORM, no creo que aún estemos en el espacio ORM. Imagínense que los datos de béisbol de las ligas americanas, nacionales y ficticias se almacenaron en formatos muy diferentes con distintos niveles de normalización. Mi trabajo consiste en leer estas fuentes de datos y colocarlos en un conjunto unificado y normalizado. Siento que el espacio ORM de actuar sobre estos objetos ocurre después de mi proceso. Soy una especie de conserje de datos, si quieres. Básicamente, no hay objetos comerciales por los que deba actuar debido a la falta de un conjunto unificado, que creo.

Editar ^ 2 : Me han llamado la atención que quizás no describí el espacio problemático con suficiente detalle. Aquí hay un ejemplo.

Imagine que tiene que crear una base de datos maestra de todos los delincuentes en los Estados Unidos. El servicio de su empresa es vender un producto que se encuentra encima y proporciona acceso a estos datos en un formato limpio y unificado.

Esta información es brindada públicamente por los 50 estados, pero en formatos tremendamente diferentes. Algunos son un archivo de datos, no normalizado. Otros son tablas normalizadas en formato CSV. Algunos son documentos de Excel. Algunos son TSV. Incluso se proporcionan algunos registros que no están completos sin intervención manual (otras fuentes de datos creadas manualmente).

El propósito de mi proyecto es hacer un "controlador" para cada uno de los 50 estados y asegurarme de que el producto final del proceso sea una base de datos maestra de delincuentes en un modelo perfecto de relación. Todo en clave correctamente, el esquema en forma perfecta, etc.


Creo que está describiendo el SQL dinámico, generando la solicitud programáticamente en el tiempo de ejecución. Esta es una característica común de Object relational Mappers como LINQ to SQL y LLBLGenPro, por nombrar algunos. Construir uno no es una tarea pequeña.

En general, los ORMs objetivan el lenguaje SQL. Usted escribe una especie de "Modelo de Objeto de Documento SQL (DOM)" que le permite construir consultas SQL programáticamente representándolas (por ejemplo) como un objeto "Solicitud". A continuación, establece propiedades en el objeto Request, como una colección de columnas, una colección de tablas y una colección Join (estos son solo ejemplos de un enfoque). El resultado sería una cadena de solicitud SQL, expuesta como una propiedad del objeto Request.

También debe permitir que el objeto Solicitud lea la definición de esquema de sus fuentes de datos. Menciona que su cláusula WHERE depende del tipo. Por lo tanto, su ensamblador SQL debe poder leer el esquema y construir la cláusula de manera apropiada.

Esto puede ser excesivo para su caso. Creo que la pregunta fundamental es, ¿requiere absolutamente consultas SQL dinámicas, o hay una opción menos compleja que satisfaga sus requisitos?


Desde el punto de vista puramente codificador, usted tiene un código largo y complejo en sus manos. No te gusta ¿Por qué? Solo puedo suponer que hay alguna duplicación de código allí. De lo contrario, ¿qué no es como? Por lo tanto, refactorícelo para eliminar la duplicación ... Sé que suena trillado, pero como no publica el código, es difícil ser más específico. ¿Puede tener un objeto que tenga métodos para cláusulas from, where e insert, para que la infraestructura del SQL no esté duplicada? Simplemente no sé qué hacer, exactamente, pero eliminar la duplicación es la clave.


Por favor, no escriba su propio ORM. Use algo como DBIx :: Class .

Todos estos problemas que menciona han sido resueltos y la implementación probada en miles de otras aplicaciones. Limítese a escribir su aplicación, no a volver a implementar las bibliotecas. Es probable que no uses DBIC en tu aplicación, pero deberías ver su enfoque de implementación; especialmente cómo crea incrementalmente ResultSets (que no son conjuntos de resultados, sino que son consultas diferidas).


Si no desea un ORM, pero desea ensamblar SQL a partir de bits sin manipulación / concatenación directa de cadenas, eche un vistazo a Fey , que puede hacer lo que desee.

Actualización: la respuesta de Aristóteles Pagaltzis es mucho mejor. Él realmente dio ejemplos de cómo se ve Fey y cómo puede ayudar.


Si no desea tratar con un ORM, a menudo tengo un código como este:

my (@columns,@tables,@wheres,@order_bys,@values); ... # Add value to those variables as needed, using push. ... # use ? for variables to be quoted # Build SQL statement my $sql = "select ".join(",",@columns). " from ".join(",",@tables). " where ".join(" and ",@wheres). " order by ".join(",",@order_bys); my $sth = $dbh->prepare($sql); $sth->execute(@values);

Simple, sin necesidad de un ORM, muy personalizable. Además, siempre encuentro que el ORM es demasiado pesado para el volumen de datos con el que estoy tratando, pero ese es otro tema.


Quieres mirar a Fey . Empecé a usarlo hace unos meses en el trabajo, y aunque la implementación todavía tiene rincones difíciles debido a su corta edad, la idea detrás de esto es sólida. F.ex., tome una consulta ligeramente adaptada del manual:

my $user = $schema->table( ''user'' ); my $q = Fey::SQL ->new_select ->select( $user->columns( ''user_id'', ''username'' ) ) ->from( $user );

Ahora puedes escribir una función como esta:

sub restrict_with_group { my ( $q, $table, @group_id ) = @_; my $group = $schema->table( ''group'' )->alias; $q ->from( $table, $group ) ->where( $group->column( ''group_id'' ), ''IN'', @group_id ); }

Esto agregará una unión interna de user a group , así como una condición WHERE . Y listo, puedes escribir lo siguiente en el programa principal:

restrict_with_group( $q, $user, qw( 1 2 3 ) );

¡Pero esta función restrict_with_group funcionará para cualquier consulta que tenga una clave foránea en la tabla de group ! Para usarlo, pase la consulta que desea restringir y la tabla a la que desea aplicar la restricción, así como los ID de grupo a los que desea restringirla.

Al final dices $q->sql( $dbh ) y obtienes una cadena de SQL que representa la consulta que has creado en el objeto $q .

Así que, básicamente, Fey te brinda las capacidades abstractas que faltan en SQL nativo. Puede extraer aspectos reutilizables de sus consultas y empaquetarlos como funciones separadas.


Me parece que debe enfocarse en el enfoque que está tomando para resolver este problema. Actualmente tiene varias fuentes de datos que debe tratar como si se tratara de una única fuente de datos. Entonces, ¿por qué mantenerlos como fuentes de datos separadas?

Dependiendo de la frecuencia con la que se actualicen los datos (o del rendimiento, la frecuencia con la que se accede), es posible que pueda combinar los datos en una fuente de datos temporal como SQLite. Si sus datos de cada estado tienen un traductor que lo llevará del formato A a su formato común en una tabla SQLite, entonces puede usar su elección de métodos para acceder a él.

Este método también permite flexibilidad ya que sus necesidades de acceso a datos pueden cambiar. Por ejemplo, si le hacen la pregunta, "¿Cuántos conductores rubios tenían multas por exceso de velocidad en cada estado?". La base de datos SQLite puede hacer esto con un solo comando, mientras que otras soluciones probablemente requieran devolver un conjunto de datos que luego deben ser analizados, agrupados y configurados para su salida.