Odkrywanie schematów za pomocą mssql-python

Klasa kursorów mssql-python udostępnia dziewięć metod metadanych, które mapują się na funkcje katalogowe ODBC. Użyj tych metod, aby programowo wykrywać tabele, kolumny, procedury składowane, klucze i indeksy. Pomagają tworzyć aplikacje oparte na danych, które dostosowują się do schematu bazy danych w czasie działania, takie jak narzędzia migracji, generatory kodu czy pulpity administracyjne.

Metoda Funkcja ODBC Zwroty Kiedy stosować
tables() SQLTables Informacje o tabelach i widokach. Bazy danych inwentarza. Zweryfikowaj istnienie tabeli przed zapytaniami.
columns() SQLColumns Szczegóły kolumny. Generuj DDL, buduj dynamiczne zapytania lub mapuj kolumny na kod.
procedures() SQLProcedures Informacje o procedurach przechowywanych. Odkryj dostępne API. Generuj opakowania wywołań procedur.
primaryKeys() SQLPrimaryKeys Główne kolumny kluczowe. Zidentyfikuj unikatowe identyfikatory wierszy na potrzeby operacji UPDATE/DELETE.
foreignKeys() SQLForeignKeys Relacje kluczy zagraniczne. Mapuj relacje tabelowe, ustalaj kolejność usuwania skryptów czyszczących.
statistics() SQLStatistics Indeks i informacje statystyczne. Sprawdź pokrycie przez indeksy na potrzeby optymalizacji wydajności.
rowIdColumns() SQLSpecialColumns (ROWID) Unikalne kolumny identyfikatorów wiersza. Znajdź najlepsze kolumny do identyfikacji konkretnych wierszy.
rowVerColumns() SQLSpecialColumns (ROWVER) Kolumny wersji wiersza. Implementuj optymistyczną współbieżność (wykrywanie współbieżnych modyfikacji).
getTypeInfo() SQLGetTypeInfo Informacje o typie danych. Odkryj obsługiwane typy kompatybilności międzyplatformowej.

Każda metoda zwraca kursor, który możesz iterować, aby uzyskać dostęp do wyników.

Tables

Lista tabel i widoków w bazie danych:

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)

parametry funkcji tables()

Następujące parametry sterują wykrywaniem tabel:

Parameter Opis
table Wzorzec nazwy tabeli (obsługuje symbole wieloznaczne % i _).
catalog Nazwa katalogu (bazy danych).
schema Schemat nazwy.
tableType Filtruj według typu: TABLE, VIEW, SYSTEM TABLE, GLOBAL TEMPORARY, , LOCAL TEMPORARY, ALIAS, . SYNONYM

kolumny wyników tables()

Metoda tables() zwraca następujące kolumny dla każdej tabeli lub widoku:

Column Opis
table_cat Nazwa katalogu (bazy danych).
table_schem Nazwa schematu.
table_name Tabela lub nazwa widoku.
table_type TABLE, VIEW, SYSTEM TABLE, GLOBAL TEMPORARY, , LOCAL TEMPORARY, ALIAS. SYNONYM
remarks Opis lub komentarze.

Sprawdź, czy istnieje tabela

Sprawdź, czy tabela istnieje, zanim wykonasz do niej zapytanie:

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

Kolumny

Pobierz informacje o kolumnach dla tabel:

# 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)

parametry funkcji columns()

Filtry do udoskonalenia odkrywania kolumn:

Parameter Opis
table Wzorzec nazwy tabeli.
catalog Nazwa katalogu (bazy danych).
schema Schemat nazwy.
column Wzór nazw kolumn.

columns() kolumny wyników

Metoda columns() zwraca szczegółowe informacje o każdej kolumnie:

Column Opis
table_cat, table_schem, table_name Identyfikatory lokalizacji.
column_name Nazwa kolumny.
data_type Kod typu danych SQL.
type_name Nazwa typu danych (na przykład varchar, int).
column_size Maksymalna długość lub precyzja.
buffer_length Rozmiar bufora dla transferów.
decimal_digits Skala dla typów numerycznych.
nullable 0 dla NOT NULL, 1 dla wartości null.
column_def Wartość domyślna.
ordinal_position Pozycja kolumny (oparta na 1).
is_nullable "YES" lub "NO".

Procedury przechowywane

Odkryj procedury przechowywane:

# 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)

parametry procedur()

Filtruj procedury przechowywane według nazwy lub schematu:

Parameter Opis
procedure Wzór nazw procedur.
catalog Nazwa katalogu (bazy danych).
schema Schemat nazwy.

procedury() kolumny wyników

Metoda procedures() zwraca metadane dla każdej procedury przechowywanej:

Column Opis
procedure_cat, procedure_schem Identyfikatory lokalizacji.
procedure_name Nazwa procedury.
num_input_params Liczba parametrów wejściowych.
num_output_params Liczba parametrów wyjściowych.
num_result_sets Liczba zestawów wyników.
remarks Description.
procedure_type Wskaźnik typu.

Klucze podstawowe

Pobierz główne kolumny kluczowe do tabeli:

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}")

parametry metody primaryKeys()

Parametry do pobierania informacji o kluczu głównym:

Parameter Opis
table Nazwa stołu (wymagana).
catalog Nazwa katalogu (bazy danych).
schema Nazwa schematu.

kolumny rezultatów primaryKeys()

Metoda primaryKeys() zwraca następujące informacje:

Column Opis
table_cat, table_schem, table_name Identyfikatory lokalizacji.
column_name Kolumna w kluczu głównym.
key_seq Pozycja w kluczu wielokolumnowym (oparty na 1).
pk_name Nazwa ograniczenia klucza głównego.

Klucze obce

Odkryj relacje kluczy zagranicznych:

# 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")

parametry foreignKeys()

Określ tabele kluczy pierwotnych lub obcych, aby odkryć relacje:

Parameter Opis
table Nazwa tabeli klucza podstawowego.
catalog Katalog kluczy podstawowych.
schema Schemat klucza głównego.
foreignTable Nazwa tabeli kluczy obcych.
foreignCatalog Katalog kluczy obcych.
foreignSchema Schemat klucza obcego.

kolumny wyników foreignKeys()

Metoda foreignKeys() zwraca następujące kolumny opisujące relacje:

Column Opis
pktable_cat, pktable_schem, pktable_name Tabela referencyjna (główna).
pkcolumn_name Kolumna referencyjna.
fktable_cat, fktable_schem, fktable_name Tabela referencyjna (zagraniczna).
fkcolumn_name Kolumna referencyjna.
key_seq Pozycja w kluczu wielokolumnowym.
update_rule Akcja na UPDATE.
delete_rule Akcja na DELETE.
fk_name Nazwa ograniczenia klucza obcego.
pk_name Nazwa ograniczenia klucza głównego.

Indeksy i statystyki

Uzyskaj informacje indeksowe dla tabeli:

# 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}")

parametry statystyczne()

Konfiguruj odkrywanie indeksów za pomocą następujących filtrów:

Parameter Domyślnie Opis
table (required) Nazwa tabeli.
catalog Żaden Nazwa katalogu (bazy danych).
schema Żaden Nazwa schematu.
unique Nieprawda Zwracaj tylko unikalne indeksy.
quick True Pomiń kosztowne pobieranie kardynalności i stron.

kolumny statystyk() wyników

Metoda statistics() zwraca informacje indeksowe i statystyczne:

Column Opis
table_cat, table_schem, table_name Identyfikatory lokalizacji.
non_unique 0 dla unikalnego, 1 dla nieunikalnego.
index_name Nazwa indeksu.
type Typ indeksu.
ordinal_position Pozycja kolumny w indeksie.
column_name Nazwa kolumny.
asc_or_desc A Na wznoszenie się, D na zniżanie.
cardinality Szacunkowa liczba wierszy.
pages Liczba stron.

Kolumny identyfikatorów wierszy

Znajdź kolumny, które jednoznacznie identyfikują wiersz:

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

Ta metoda zwraca najlepszy zestaw kolumn do jednoznacznej identyfikacji wiersza, który może być kluczem głównym lub unikalnym indeksem.

Kolumny wersji wiersza

Znajdź kolumny, które są automatycznie aktualizowane po zmianie wartości wiersza. Używaj kolumn wersji wiersza do optymistycznej kontroli współbieżności, gdzie czytasz wersję wiersza, wprowadzasz zmiany, a następnie sprawdzasz, czy aktualna wersja wiersza jest taka sama przed zapisaniem:

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

Wynik zazwyczaj zawiera kolumny rowversion/timestamp używane na potrzeby optymistycznej współbieżności.

Informacje o typie danych

Uzyskaj informacje o obsługiwanych typach danych SQL:

# 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}")

getTypeInfo() parametry

Opcjonalne parametry filtrowania obsługiwanych typów SQL:

Parameter Opis
sqlType Stała typu SQL (pomiń dla wszystkich typów).

Zagadnienia dotyczące zabezpieczeń

Caution

Metody te ujawniają metadane schematu bazy danych. Chociaż same metody są bezpieczne do wykonania, zwracane informacje ujawniają strukturę bazy danych (nazwy tabel, nazwy kolumn, relacje, typy danych).

  • Nie udostępniaj surowych metadanych nieufnym użytkownikom.
  • Sanityzować lub filtrować wyniki w aplikacjach wielodostępnych.
  • Ogranicz dostęp do aplikacji dostępnych z zewnątrz.

Przykład: Wygenerowanie raportu schematu

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")