Domanda

Mi sono chiesto se esiste un codice che permetta di rappresentare SQL sotto forma di un albero di oggetti che può essere assemblato, modificato e infine reso in SQL valido?

In cima alla mia testa potrebbe sembrare qualcosa del genere ...

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

Questo è solo un esempio e la cosa là fuori potrebbe funzionare in modo totalmente diverso, ma sì, mi piacerebbe sapere cosa c'è di strano in questo senso.

UPDATE:

Sono consapevole delle numerose possibilità di utilizzo delle tecnologie ORM per ottenere i miei risultati dal DB, ma cercavo un modello per lo stesso SQL. So che il livello di astrazione è piuttosto basso, ma potrebbe consentire una situazione in cui più collaboratori possono lavorare su un'istruzione SQL (più join, più ubicazioni) che può quindi essere & Quot; rendering & Quot; alla fine della fase di compilazione.

È stato utile?

Soluzione

Il pacchetto python SQLAlchemy ha un livello ORM, ma ha anche un livello di generazione SQL.

[Mi rendo conto che hai taggato questo post c # e .net, ma ho pensato che ti sarebbe piaciuto vedere cos'altro c'è là fuori]

Ecco un esempio di codice:

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.

In genere, si esegue l'istruzione utilizzando SQLAlchemy per connettersi a un database. Quindi puoi fare:

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

Spero che questo aiuti.

Altri suggerimenti

Hibernate ha il suo Hibernate Query Language (HQL) che rappresenta costrutti simili a SQL come oggetti.

Un OR-Mapper, come LINQ

Ecco alcuni esempi:

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;

Alcuni link per iniziare:

Vedi quanto sopra e ho visto più di un programmatore proseguire su questa strada. (E ho detto a più di un programmatore che ho visto più di un programmatore ..., ma di solito finiscono per scoprire da soli quanto funziona bene.)

La difficoltà che vedo è che stai aggiungendo una sostanziale complessità senza offrire molto in termini di astrazione. Devi praticamente sapere con quale SQL finirai comunque.

(Almeno nella misura in cui lo schema è rappresentato nell'illustrazione, in cui si specificano direttamente le clausole. Gli ORM si estendono ben oltre.)

In .Net, Linq fa praticamente quello di cui stai parlando.

Se stai ancora utilizzando .NET 2.0 e non sei passato a LINQ, allora creerei una classe di istruzione di base, quindi creerei classi che consentono un modello di decorazione.

In questo modo puoi semplicemente continuare ad aggiungere ciò di cui hai bisogno alla tua dichiarazione di base.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top