Pregunta

Me he estado preguntando si hay algún código que permita representar SQL en forma de algún árbol de objetos que pueda ensamblarse, modificarse y luego finalmente convertirse en SQL válido.

De la parte superior de mi cabeza podría verse algo así ...

var stmnt = new Statement();
stmnt
  .AddMaster("Customer")
  .Show("Firstname, "Lastname")
  .AddJoin("Address", "ID", "CustomerID")
  .Show("Street", "City");
stmnt.WhereStatement()
  .AddParameter("Address.City", Op.Equal);

string sql = stmnt.Generate();
// select a.FirstName, a.LastName, b.Street, b.City
// from Customer a
// join Address b on b.CustomerID = a.ID
// where b.City = :p1

Este es solo un ejemplo y la cosa puede funcionar de manera totalmente diferente, pero sí, me encantaría escuchar lo que está al respecto a ese respecto.

ACTUALIZACIÓN:

Soy consciente de las numerosas posibilidades de usar las tecnologías ORM para obtener mis resultados de la base de datos, pero buscaba un modelo para el SQL en sí. Sé que el nivel de abstracción es bastante bajo, pero posiblemente podría permitir una situación en la que varios colaboradores puedan trabajar en una instrucción SQL (múltiples uniones, múltiples dónde) que luego se puede & "; Representa &"; al final de la fase de construcción.

¿Fue útil?

Solución

El paquete Python SQLAlchemy tiene una capa ORM, pero también tiene una capa de generación de SQL.

[Me doy cuenta de que etiquetaste esta publicación c # y .net, pero pensé que te gustaría ver qué más hay ahí fuera]

Aquí hay un código de ejemplo:

from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.sql import select

metadata = MetaData()

# Make a basic customer table.
Customer = Table('Customer',
                 metadata,
                 Column('ID', Integer, primary_key=True),
                 Column('FirstName', String),
                 Column('LastName', String))

# Make a basic address table
Address = Table('Address',
                metadata,
                Column('ID', Integer, primary_key=True),
                Column('City', String),
                Column('Street', String),
                Column('CustomerID', None, ForeignKey('Customer.ID')))


# Generate some sql
stmt = select([Customer.c.FirstName,
               Customer.c.LastName,
               Address.c.Street,
               Address.c.City],
              from_obj=Customer.join(Address),
              whereclause=Address.c.City == 'Wellington')

# Display
print stmt
# output:
SELECT "Customer"."FirstName", "Customer"."LastName", "Address"."Street", "Address"."City" 
FROM "Customer" JOIN "Address" ON "Customer"."ID" = "Address"."CustomerID" 
WHERE "Address"."City" = :City_1

# note that SQLAlchemy picked up the join condition from the foreign key.
# you can specify other join conditions if you want.

Normalmente, ejecutaría la instrucción utilizando SQLAlchemy para conectarse a una base de datos. Entonces puedes hacer:

for row in stmt.execute():
    print 'Name:', row.c.FirstName, row.c.LastName, 'City:', row.c.City

Espero que esto ayude.

Otros consejos

Hibernate tiene su propio lenguaje de consulta Hibernate (HQL) que representa construcciones similares a SQL como objetos.

Un OR-Mapper, como LINQ

Aquí hay algunos ejemplos:

from c in customers
where c.LastName.StartsWith("A")
select c

//

var q = from c in db.Contact
           where c.DateOfBirth.AddYears(35) > DateTime.Now
           orderby c.DateOfBirth descending
           select c;

Algunos enlaces para comenzar:

Vea lo anterior, y he visto a más de un programador ir por este camino. (Y le he dicho a más de un programador que he visto a más de un programador ..., pero generalmente terminan descubriendo por sí mismos qué tan bien funciona).

La dificultad que veo es que está agregando una complejidad sustancial sin ofrecer mucho en cuanto a abstracción. De todos modos, necesita saber con qué SQL terminará.

(Al menos en la medida en que el patrón es el representado en su ilustración, donde está especificando las cláusulas directamente. Los ORM se resumen mucho más allá de eso).

En .Net, Linq hace más o menos de lo que estás hablando.

Si todavía está usando .NET 2.0 y no se ha movido a LINQ, entonces crearía una clase de declaración base, luego crearía clases que permitan un patrón de decorador.

De esa manera, puede seguir agregando lo que necesita a su declaración base.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top