Scoperta dello schema con mssql-python

La classe cursore mssql-python fornisce nove metodi di metadati che si mappano alle funzioni del catalogo ODBC. Usa questi metodi per scoprire tabelle, colonne, stored procedure, chiavi e indici in modo programmativo. Ti aiutano a costruire applicazioni basate sui dati che si adattano allo schema del database in runtime, come strumenti di migrazione, generatori di codice o dashboard amministrative.

metodo Funzione ODBC Returns Quando utilizzare
tables() SQLTables Informazioni su tabelle e visualizzazioni. Database di inventario. Valida l'esistenza delle tabelle prima delle query.
columns() SQLColumns Dettagli della colonna. Genera DDL, crea query dinamiche o mappa colonne nel codice.
procedures() SQLProcedures Informazioni sulle procedure memorizzate. Scopri le API disponibili. Genera wrapper per chiamate di procedura.
primaryKeys() SQLPrimaryKeys Colonne chiave principali. Identifica gli identificatori univoci di riga per le operazioni UPDATE/DELETE.
foreignKeys() SQLForeignKeys Relazioni chiave straniere. Mappare le relazioni delle tabelle, determina l'ordine di cancellazione per gli script di pulizia.
statistics() SQLStatistics Informazioni su indice e statistiche. Verificare la copertura degli indici per l'ottimizzazione delle prestazioni.
rowIdColumns() SQLSpecialColumns (ROWID) Colonne uniche di identificatore di riga. Trova le colonne migliori da usare per identificare righe specifiche.
rowVerColumns() SQLSpecialColumns (ROWVER) Colonne della versione di riga. Implementare la concorrenza ottimista (rilevare modifiche concorrenti).
getTypeInfo() SQLGetTypeInfo Informazioni sui tipi di dati. Scopri i tipi supportati per la compatibilità multipiattaforma.

Ogni metodo restituisce un cursore che puoi iterare per accedere ai risultati.

Tables

Elenca le tabelle e le viste nel database:

cursor = conn.cursor()

# List all tables
for row in cursor.tables():
    print(f"{row.table_schem}.{row.table_name} ({row.table_type})")

# Filter by name (supports wildcards % and _)
for row in cursor.tables(table="Product%"):
    print(row.table_name)

# Filter by schema
for row in cursor.tables(schema="Sales"):
    print(row.table_name)

# Filter by type
for row in cursor.tables(tableType="TABLE"):  # Excludes views
    print(row.table_name)

parametri di tables()

I seguenti parametri controllano la scoperta della tabella:

Parametro Descrizione
table Modello dei nomi delle tabelle (supporti % e _ wildcard).
catalog Nome del catalogo (database).
schema Schema del nome dello schema.
tableType Filtra per tipo: TABLE, VIEW, SYSTEM TABLE, GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, , SYNONYM.

Colonne dei risultati delle tabelle()

Il tables() metodo restituisce le seguenti colonne per ogni tabella o vista:

Column Descrizione
table_cat Nome del catalogo (database).
table_schem Nome dello schema.
table_name Nome della tabella o della vista.
table_type TABLE, VIEW, SYSTEM TABLE, GLOBAL TEMPORARY, LOCAL TEMPORARY, ALIAS, , . SYNONYM
remarks Descrizione o commenti.

Controlla se esiste una tabella

Verifica che una tabella esista prima di interrogarla:

if cursor.tables(table="Product", schema="Production").fetchone():
    print("Product table exists")
else:
    print("Product table not found")

Colonne

Recupera le informazioni sulle colonne per le tabelle:

# All columns in a table
for row in cursor.columns(table="Product", schema="Production"):
    print(f"{row.column_name}: {row.type_name}({row.column_size})")
    print(f"  Nullable: {row.nullable}, Position: {row.ordinal_position}")

# Filter by column name
for row in cursor.columns(table="Product", schema="Production", column="List%"):
    print(row.column_name)

Parametri di columns()

Filtri per affinare la scoperta delle colonne:

Parametro Descrizione
table Schema del nome della tabella.
catalog Nome del catalogo (database).
schema Schema del nome dello schema.
column Modello dei nomi delle colonne.

colonne di risultato di columns()

Il columns() metodo restituisce informazioni dettagliate su ogni colonna:

Column Descrizione
table_cat, table_schem, table_name Identificatori di posizione.
column_name Nome colonna.
data_type Codice di tipo dati SQL.
type_name Nome del tipo di dato (ad esempio, varchar, int).
column_size Massima lunghezza o precisione.
buffer_length Dimensione del buffer per i trasferimenti.
decimal_digits Scala per i tipi numerici.
nullable 0 per NON NULLO, per 1 nullabile.
column_def Valore predefinito.
ordinal_position Posizione della colonna (basata a 1).
is_nullable "YES" o "NO".

Procedure memorizzate

Scopri le procedure archiviate:

# List all procedures
for row in cursor.procedures():
    print(f"{row.procedure_schem}.{row.procedure_name}")

# Filter by name pattern
for row in cursor.procedures(procedure="Get%"):
    print(row.procedure_name)

parametri di procedures()

Filtra le procedure memorizzate per nome o schema:

Parametro Descrizione
procedure Schema del nome della procedura.
catalog Nome del catalogo (database).
schema Modello del nome dello schema.

Colonne del risultato di procedures()

Il procedures() metodo restituisce i metadati per ogni procedura memorizzata:

Column Descrizione
procedure_cat, procedure_schem Identificatori di posizione.
procedure_name Nome della procedura.
num_input_params Numero di parametri di input.
num_output_params Numero di parametri di output.
num_result_sets Numero di insiemi di risultati.
remarks Description.
procedure_type Indicatore di tipo.

Chiavi primarie

Ottieni le colonne chiave primarie per una tabella:

for row in cursor.primaryKeys(table="Product", schema="Production"):
    print(f"PK column: {row.column_name} (position {row.key_seq})")
    print(f"Constraint name: {row.pk_name}")

parametri di primaryKeys()

Parametri per recuperare le informazioni chiave primarie:

Parametro Descrizione
table Nome della tabella (obbligatorio).
catalog Nome del catalogo (database).
schema Nome dello schema.

colonne dei risultati primaryKeys()

Il primaryKeys() metodo restituisce le seguenti informazioni:

Column Descrizione
table_cat, table_schem, table_name Identificatori di posizione.
column_name Colonna nella chiave primaria.
key_seq Posizione nella chiave multicolonna (indicizzata a partire da 1).
pk_name Nome del vincolo chiave primario.

Chiavi esterne

Scopri le relazioni con le chiavi estere:

# Foreign keys from a table (outbound references)
for row in cursor.foreignKeys(table="SalesOrderDetail", schema="Sales"):
    print(f"FK {row.fk_name}:")
    print(f"  {row.fktable_name}.{row.fkcolumn_name}")
    print(f"  -> {row.pktable_name}.{row.pkcolumn_name}")

# Foreign keys to a table (inbound references)
for row in cursor.foreignKeys(foreignTable="Product", foreignSchema="Production"):
    print(f"{row.fktable_name} references Product")

parametri di foreignKeys()

Specifica le tabelle delle chiavi primarie o esterne per scoprire le relazioni:

Parametro Descrizione
table Nome della tabella della chiave primaria.
catalog Catalogo delle chiavi primarie.
schema Schema della chiave primaria.
foreignTable Nome della tabella della chiave esterna.
foreignCatalog Catalogo di chiavi estere.
foreignSchema Schema della chiave esterna.

colonne dei risultati foreignKeys()

Il foreignKeys() metodo restituisce le seguenti colonne che descrivono le relazioni:

Column Descrizione
pktable_cat, pktable_schem, pktable_name Tabella di riferimento (primaria).
pkcolumn_name Colonna citata.
fktable_cat, fktable_schem, fktable_name Tabella di riferimento (straniera).
fkcolumn_name Colonna di riferimento.
key_seq Posizione nella chiave multi-colonna.
update_rule Azione su UPDATE.
delete_rule Azione su DELETE.
fk_name Nome del vincolo di chiave esterna.
pk_name Nome del vincolo chiave primario.

Indici e statistiche

Ottieni informazioni sull'indice per una tabella:

# All indexes on a table
for row in cursor.statistics(table="Product", schema="Production"):
    if row.index_name:  # Skip table statistics row
        print(f"Index: {row.index_name}")
        print(f"  Column: {row.column_name} (position {row.ordinal_position})")
        print(f"  Unique: {not row.non_unique}")

# Only unique indexes
for row in cursor.statistics(table="Product", schema="Production", unique=True):
    print(f"Unique index: {row.index_name}")

parametri statistici()

Configura la scoperta degli indici con questi filtri:

Parametro Impostazione predefinita Descrizione
table (obbligatorio) Nome della tabella.
catalog None Nome del catalogo (database).
schema None Nome dello schema.
unique Falso Restituisci solo indici unici.
quick True Evita il costoso recupero di cardinalità/pagine.

Statistica() Colonne dei risultati

Il statistics() metodo restituisce informazioni su indice e statistiche:

Column Descrizione
table_cat, table_schem, table_name Identificatori di posizione.
non_unique 0 per unico, 1 per non unico.
index_name Nome dell'indice.
type Tipo di indice.
ordinal_position Posizione della colonna nell'indice.
column_name Nome colonna.
asc_or_desc A per salire, D per scendere.
cardinality Stima del numero di righe.
pages Numero di pagine.

Colonne di identificazione della riga

Trova colonne che identificano in modo univoco una riga:

for row in cursor.rowIdColumns(table="Product", schema="Production"):
    print(f"Row ID column: {row.column_name} ({row.type_name})")

Questo metodo restituisce il miglior insieme di colonne per identificare univocamente una riga, che potrebbe essere la chiave primaria o un indice univoco.

Colonne della versione riga

Trova colonne che vengono aggiornate automaticamente quando cambia il valore di una riga. Usa le colonne delle versioni della riga per un controllo ottimista della concorrenza, dove leggi la versione di una riga, apporti modifiche e poi verifichi che la versione corrente della riga sia la stessa prima di scrivere:

for row in cursor.rowVerColumns(table="Product", schema="Production"):
    print(f"Version column: {row.column_name}")

Il risultato include tipicamente le colonne rowversion/timestamp utilizzate per la concorrenza ottimistica.

Informazioni sul tipo di dati

Ottieni informazioni sui tipi di dati SQL supportati:

# All supported types
for row in cursor.getTypeInfo():
    print(f"{row.type_name}: {row.data_type}")
    print(f"  Max size: {row.column_size}")
    print(f"  Nullable: {row.nullable}")

# Specific type
for row in cursor.getTypeInfo(sqlType=mssql_python.SQL_VARCHAR):
    print(f"VARCHAR max size: {row.column_size}")

parametri di getTypeInfo()

Parametri opzionali per filtrare i tipi SQL supportati:

Parametro Descrizione
sqlType Costante di tipo SQL (omettere per tutti i tipi).

Considerazioni relative alla sicurezza

Attenzione

Questi metodi espongono i metadati degli schemi del database. Sebbene i metodi stessi siano sicuri da eseguire, le informazioni restituite rivelano la struttura del tuo database (nomi di tabelle, nomi di colonne, relazioni, tipi di dati).

  • Non esporre metadati grezzi a utenti non affidabili.
  • Sanitizzare o filtrare i risultati nelle applicazioni multitenant.
  • Limita l'accesso nelle applicazioni rivolte all'esterno.

Esempio: Generare un report sullo schema

def describe_table(conn, table_name):
    """Generate a schema description for a table."""
    cursor = conn.cursor()
    
    print(f"\n=== {table_name} ===\n")
    
    # Columns
    print("Columns:")
    for col in cursor.columns(table=table_name):
        nullable = "NULL" if col.nullable else "NOT NULL"
        print(f"  {col.column_name}: {col.type_name}({col.column_size}) {nullable}")
    
    # Primary key
    print("\nPrimary Key:")
    pk_cols = cursor.primaryKeys(table=table_name).fetchall()
    if pk_cols:
        pk_names = ", ".join(row.column_name for row in pk_cols)
        print(f"  {pk_cols[0].pk_name}: ({pk_names})")
    else:
        print("  (none)")
    
    # Foreign keys
    print("\nForeign Keys:")
    for fk in cursor.foreignKeys(table=table_name):
        print(f"  {fk.fk_name}: {fk.fkcolumn_name} -> {fk.pktable_name}.{fk.pkcolumn_name}")
    
    # Indexes
    print("\nIndexes:")
    for idx in cursor.statistics(table=table_name):
        if idx.index_name:
            unique = "UNIQUE " if not idx.non_unique else ""
            print(f"  {unique}{idx.index_name}: {idx.column_name}")

# Usage
describe_table(conn, "Product")