Karakterláncok és Unicode kezelése

A Microsoft SQL több stringtípust biztosít, amelyeket az mssql-python illesztőprogram Python str objektumokra képez. A legfontosabb döntés az, hogy a varchar (nem Unicode-os) vagy a nvarchar (Unicode) változatot használjuk:

  • Használd, nvarchar ha az adataid tartalmazhatnak ASCII-n kívüli karaktereket, például neveket, címeket vagy felhasználó által generált tartalmat bármely nyelven.
  • Használd varchar , ha az adatok szigorúan ASCII-ből állnak (kódok, azonosítók, e-mail címek), és szeretnél tárolni a tárhelyet. varchar 1 bájtot használ karakterenként; nvarchar Karakterenként 2 bájtot használ.
SQL-típus Unicode Max. hossz Python-típus
char(n) No 8,000 str
varchar(n) No 8,000 str
varchar(max) No 2 GB str
nchar(n) Yes 4,000 str
nvarchar(n) Yes 4,000 str
nvarchar(max) Yes 2 GB str
text No 2 GB (elavult) str
ntext Yes 2 GB (elavult) str

Alapszintű sztringműveletek

Az illesztőprogram minden Microsoft SQL string típust Python str objektumokra képez le.

Stringek beszedése és visszahívása

Használj paraméterezett lekérdezéseket a karakterlánc-adatok biztonságos beszúrására és lekérésére az adatbázisból.

import mssql_python

conn = mssql_python.connect(connection_string)
cursor = conn.cursor()

# Create temp table for demo
cursor.execute("""
    CREATE TABLE #StringDemo (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        Name NVARCHAR(100),
        Email NVARCHAR(200)
    )
""")

# Insert string data
cursor.execute(
    "INSERT INTO #StringDemo (Name, Email) VALUES (%(name)s, %(email)s)",
    {"name": "Alice Smith", "email": "alice@example.com"}
)
conn.commit()

# Retrieve string data
cursor.execute("SELECT Name, Email FROM #StringDemo WHERE ID = 1")
row = cursor.fetchone()
print(row.Name)   # 'Alice Smith'
print(row.Email)  # 'alice@example.com'

Különleges karakterekkel rendelkező húrok

Kezeld az idézőjeleket, szögletzárójeleket és más speciális karaktereket a láncsorokban paraméterezett lekérdezésekkel.

# Quotes and special characters handled automatically
cursor.execute("""
    CREATE TABLE #Notes (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        Title NVARCHAR(200),
        Content NVARCHAR(MAX)
    )
""")
cursor.execute(
    "INSERT INTO #Notes (Title, Content) VALUES (%(title)s, %(content)s)",
    {
        "title": "O'Brien's Report",
        "content": 'Contains "quotes" and special chars: <>&'
    }
)
conn.commit()

Unicode-támogatás

Használjon nvarchar oszlopokat és Pythonnalstr bármilyen nyelvű szöveg tárolására és lekérésére.

Unicode szöveg tárolása

Unicode-tartalmat úgy szúrhat be, hogy Python-karakterláncokat ad át paraméterezett lekérdezéseknek; az illesztőprogram ezeket UTF-16LE kódolásúra alakítja nvarchar oszlopok esetén.

# International characters - use nvarchar columns
cursor.execute("""
    CREATE TABLE #Messages (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        Content NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #Messages (Content) VALUES (%(msg)s)
""", {"msg": "Hello 你好 مرحبا שלום 🎉"})

cursor.execute("SELECT Content FROM #Messages WHERE ID = 1")
row = cursor.fetchone()
print(row.Content)  # 'Hello 你好 مرحبا שלום 🎉'

Unicode különböző írásmódokban

Több nyelvet és szkriptet támogassanak egyetlen táblában nvarchar oszlopok és tömeges beillesztések használatával.

messages = [
    {"lang": "English", "text": "Hello, World!"},
    {"lang": "Chinese", "text": "你好,世界!"},
    {"lang": "Japanese", "text": "こんにちは世界!"},
    {"lang": "Korean", "text": "안녕하세요, 세상!"},
    {"lang": "Arabic", "text": "مرحبا بالعالم!"},
    {"lang": "Hebrew", "text": "שלום עולם!"},
    {"lang": "Russian", "text": "Привет мир!"},
    {"lang": "Greek", "text": "Γειά σου Κόσμε!"},
    {"lang": "Emoji", "text": "👋🌍✨🎉"},
]

cursor.execute("""
    CREATE TABLE #Greetings (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        Language NVARCHAR(50),
        Message NVARCHAR(200)
    )
""")
cursor.executemany("""
    INSERT INTO #Greetings (Language, Message) VALUES (%(lang)s, %(text)s)
""", messages)
conn.commit()

Biztosítsuk a nvarchar oszlopokat Unicode számára

Mindig definiáld az oszlopokat nvarcharként a varchar helyett, ha az adataid nem ASCII karaktereket tartalmazhatnak.

-- For Unicode data, always use nvarchar, not varchar
CREATE TABLE #UnicodeDemo (
    ID INT IDENTITY PRIMARY KEY,
    Name NVARCHAR(100),        -- Supports Unicode
    Description NVARCHAR(MAX)  -- Supports large Unicode text
);

A húrhossz megfontolása

Válassz fix és változó hosszúságú típusok között az alapján, hogy mennyire konzisztens az adathosszaid.

Fix kontra változó hosszúság

A Microsoft SQL char(n) padjai az értékeket a bejelentett hosszúsághoz követő szóközekkel jelölik. Ez a párnázás tárhelyet pazarol a változó hosszúságú adatok esetében, de javíthatja a rögzített szélességű oszlopok, például az országkódok teljesítményét. A legtöbb sztringoszlop esetén használd a varchar(n) elemet.

Az alábbi példa mutatja a különbséget abban, hogyan kezelik a párolt és nem párolt oszlopok adatlekérését:

# char(6) pads to fixed length
cursor.execute(
    "SELECT StateProvinceCode FROM Person.StateProvince WHERE StateProvinceID = 1"
)  # nchar(6) column
row = cursor.fetchone()
print(repr(row.StateProvinceCode))  # 'AB    ' - right-padded with spaces

# nvarchar stores actual length
cursor.execute(
    "SELECT Name FROM Person.StateProvince WHERE StateProvinceID = 1"
)  # nvarchar column
row = cursor.fetchone()
print(repr(row.Name))  # 'Alberta' - no padding

Záró szóközök kezelése

Rögzített hosszúságú karakteroszlopokból történő adatlekéréskor használd a rstrip() elemet a Microsoft SQL Server által hozzáadott kitöltő szóközök eltávolítására.

# Strip trailing spaces from char columns
cursor.execute("SELECT ProductNumber FROM Production.Product")
for row in cursor:
    code = row.ProductNumber.rstrip()  # Remove trailing spaces
    print(f"Code: '{code}'")

Nagy húrok (MAX típusok)

Az nvarchar(max) and varchar(max) típusok akár 2 GB-ig is támogatnak stringeket, amelyek ideálisak nagy szöveges dokumentumok, JSON vagy XML tartalom tárolására.

# Large text content
large_content = "x" * 100000  # 100K characters

cursor.execute("""
    CREATE TABLE #Documents (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        Content NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #Documents (Content) VALUES (%(content)s)
""", {"content": large_content})

cursor.execute("SELECT Content FROM #Documents WHERE ID = 1")
row = cursor.fetchone()
print(len(row.Content))  # 100000

Sorok összehasonlítása és összeállítása

A Microsoft SQL string összehasonlító viselkedése az adatbázisban vagy oszlopban található összeállítási halmaztól függ.

Betűérzékenység

A Microsoft SQL string összehasonlítása az összeállítástól függ. Alapértelmezés szerint a legtöbb adatbázis kis- és nagybetűket nem megkülönböztető rendezést használ, de ezt a COLLATE záradékkal felülbírálhatja.

# Case-insensitive collation (default for many databases)
cursor.execute("SELECT * FROM Person.Person WHERE LastName = %(name)s", {"name": "smith"})
# Might match 'Smith', 'SMITH', 'smith' depending on collation

# For case-sensitive comparison
cursor.execute("""
    SELECT * FROM Person.Person 
    WHERE LastName COLLATE Latin1_General_CS_AS = %(name)s
""", {"name": "Smith"})

LIKE mintás egyeztetés

Használd a LIKE operátort helyettesítő karakterekkel a karakterminták kereséséhez; a speciális karaktereket szögletes zárójeles jelöléssel escape-eld, hogy literális karakterekre illeszkedjenek.

# Wildcard searches
search_term = "Road"
cursor.execute("""
    SELECT Name FROM Production.Product WHERE Name LIKE %(pattern)s
""", {"pattern": f"%{search_term}%"})

# Escape special characters in search
def escape_like(value: str) -> str:
    """Escape LIKE wildcards in search value."""
    return value.replace("[", "[[]").replace("%", "[%]").replace("_", "[_]")

search = "100%"
cursor.execute("""
    SELECT Name FROM Production.Product WHERE Name LIKE %(pattern)s
""", {"pattern": f"%{escape_like(search)}%"})

Kódolási szempontok

A kódolási viselkedés a Microsoft SQL oszloptípusától és a forrás összeállításától függ.

Kódolási feltételezések és Unicode alapértelmezések

Az mssql-python illesztőprogram automatikusan kezeli a kódolást a Microsoft SQL oszloptípusa alapján. Alapértelmezés szerint a karakterlánc-paraméterek UTF-16LE kódolással lesznek elküldve az nvarchar oszlopokhoz, a varchar oszlopokhoz pedig az adatbázis rendezési beállításának megfelelően:

Oszloptípus Huzalkódolás Python-eredmény
\, \, \ UTF-16LE str (a sofőr által dekódolva)
\, \, \ Adatbázis vagy oszlop összeállítási kódolás str (a meghajtó által a forráskódolással dekódolva)

A Python karakterláncai belsőleg mindig Unicode formátumúak. Amikor átengedsz egy str paramétert, a meghajtó kódolja azt a céloszlop típusához. Alapértelmezés szerint az illesztőprogram a karakterlánc-paramétereket nvarchar (Unicode) formátumban küldi, így a karakterek az adatbázis-kollációtól függetlenül megőrződnek. Az varchar oszlopok esetében az UTF-8 csak akkor érvényes, ha az adatbázis vagy oszlop UTF-8-kompatibilis összeállítást használ.

Ha az oszlop típusa varchar, és nem Unicode-adatokat kell küldened, hogy pontosan megfeleljenek az oszlop típusának (például az implicit konverziós figyelmeztetések elkerülése érdekében), használd a(z) setinputsizes() elemet az alapértelmezés felülbírálásához:

import mssql_python

conn = mssql_python.connect(connection_string)
cursor = conn.cursor()

# Create temp table for demo
cursor.execute("CREATE TABLE #AsciiTable (Code VARCHAR(100))")

cursor.setinputsizes([(mssql_python.SQL_VARCHAR, 100, 0)])
cursor.execute(
    "INSERT INTO #AsciiTable (Code) VALUES (?)",
    ("ABC123",)
)
conn.commit()

A legtöbb alkalmazásnál az alapértelmezett viselkedés helyes. Csak akkor írd felül, ha implicit konverziós figyelmeztetéseket látsz a lekérdezési tervekben, vagy egy adott varchar összeállítást kell egyeztetned.

Kapcsolatkódolás

Az mssql-python illesztőprogram automatikusan kezeli a kapcsolat kódolását a Microsoft SQL Server verziója és konfigurációja alapján. Mivel a Python stringek Unicode, az illesztőprogram megfelelően kódolja őket (UTF-8 vagy UTF-16) a céladattípushoz. Nem kell manuálisan konfigurálni a kapcsolati kódolást.

VARCHAR oszlopok örökségi összefoglalókkal.

A Windows-1252 (CP1252) összeállításokkal rendelkező adatbázisok, Latin1_General_CI_ASpéldául , kiterjesztett latin karaktereket (például , , és akcentusos karaktereket) tárolnak oszlopokban varchar CP1252 kódolással. A sofőr minden platformon helyesen dekódolja ezeket a karaktereket.

Ez a különbség számít a többplatformos telepítéseknél: ugyanaz varchar az adat, amely helyesen olvasható Windows-on, Linuxon is helyesen olvasható, külön konfiguráció nélkül.

# Create a temp table with a varchar column and insert extended Latin characters
cursor.execute("CREATE TABLE #Products (Name VARCHAR(100))")
cursor.execute("INSERT INTO #Products (Name) VALUES (%(name)s)", {"name": "Café €100 ™"})
conn.commit()

# CP1252 characters in varchar columns are decoded correctly on all platforms
cursor.execute("SELECT Name FROM #Products WHERE Name LIKE '%€%'")
for row in cursor:
    print(row.Name)  # Correct on both Windows and Linux

Ha a séma lehetővé teszi, a varchar oszlopok nvarchar-re történő áttelepítése teljes mértékben kiküszöböli a kódolási kétértelműséget, és az összes Unicode-karaktert támogatja.

Fájlkódolás

Amikor fájlokat olvas az adatbázisba való beillesztéshez, határozd meg a megfelelő kódolást az Unicode tartalom megőrzéséhez.

# Reading files with explicit encoding
def insert_file_content(cursor, conn, file_path: str, encoding: str = "utf-8"):
    with open(file_path, "r", encoding=encoding) as f:
        content = f.read()
    
    cursor.execute(
        "INSERT INTO #FileContent (Content) VALUES (%(content)s)",
        {"content": content}
    )
    conn.commit()

Gyakori sztringműveletek

Ezek a példák a Python és SQL esetében is gyakori string-manipulációs mintákat fednek le.

Összeláncolás

A stringeket össze lehet kötni Python-ban a beillesztés előtt, vagy SQL string operátoraival a szerveren.

# Concatenate in Python before insert
first_name = "Alice"
last_name = "Smith"
full_name = f"{first_name} {last_name}"

cursor.execute("""
    CREATE TABLE #ConcatDemo (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        FullName NVARCHAR(200)
    )
""")
cursor.execute(
    "INSERT INTO #ConcatDemo (FullName) VALUES (%(name)s)",
    {"name": full_name}
)

# Or concatenate in SQL
cursor.execute("""
    SELECT FirstName + ' ' + LastName AS FullName FROM Person.Person
""")

Sztringformázás

Használj formázást Pythonban, hogy a karakterláncokat pénznemmel, térközkitöltéssel vagy igazítással jelenítsd meg, mielőtt megmutatod őket a felhasználóknak.

from decimal import Decimal

# Format for display
cursor.execute("SELECT Name, ListPrice FROM Production.Product WHERE ListPrice > 0")
for row in cursor.fetchall()[:5]:
    print(f"{row.Name}: ${row.ListPrice:.2f}")

# Pad strings
cursor.execute("SELECT ProductNumber FROM Production.Product")
for row in cursor.fetchall()[:5]:
    padded = row.ProductNumber.ljust(15)  # Left-justify, pad to 15 chars
    print(f"[{padded}]")

NULL kontra üres string

A Microsoft SQL a NULL és az üres string ('') különböző értékeknek kezeli. A NULL jelentése "ismeretlen", míg az üres string "ismert, hogy üres". Válassz egy konvenciót a jelentkezésedhez, és légy következetes. A legtöbb alkalmazás a NULL-t használja a hiányzó opcionális mezők esetén.

Az alábbi példa bemutatja, hogyan lehet megkülönböztetni a NULL és az üres stringet:

# NULL is different from empty string
cursor.execute("""
    CREATE TABLE #NullDemo (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        Name NVARCHAR(100),
        MiddleName NVARCHAR(100)
    )
""")
cursor.execute("""
    INSERT INTO #NullDemo (Name, MiddleName) 
    VALUES (%(name)s, %(middle)s)
""", {"name": "Alice", "middle": None})  # NULL

cursor.execute("""
    INSERT INTO #NullDemo (Name, MiddleName) 
    VALUES (%(name)s, %(middle)s)
""", {"name": "Bob", "middle": ""})  # Empty string

# Query differences
cursor.execute("SELECT * FROM #NullDemo WHERE MiddleName IS NULL")
cursor.execute("SELECT * FROM #NullDemo WHERE MiddleName = ''")

Levágási műveletek

A Python karakterlánc-metódusaival távolítsd el a kezdő, a záró vagy mindkét oldali üres karaktereket az adatbázisból lekért értékekből.

cursor.execute("SELECT Name FROM Production.Product")
for row in cursor:
    # Remove whitespace
    trimmed = row.Name.strip()  # Both ends
    left_trimmed = row.Name.lstrip()
    right_trimmed = row.Name.rstrip()

JSON-karakterlánc adat

Tárold a JSON dokumentumokat nvarchar(max) oszlopokban, és kérdezd őket a Microsoft SQL JSON függvényeivel.

Tárold a JSON-t nvarchar néven

Szerializálja a Python-szótárakat JSON-karakterláncokká, és szúrja be őket nvarchar oszlopokba; majd kérje le őket, és deszerializálja vissza Python-objektumokká.

import json

data = {"name": "Alice", "scores": [95, 87, 91], "active": True}
json_string = json.dumps(data)

cursor.execute("""
    CREATE TABLE #Configs (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        ConfigData NVARCHAR(MAX)
    )
""")
cursor.execute("""
    INSERT INTO #Configs (ConfigData) VALUES (%(data)s)
""", {"data": json_string})

# Retrieve and parse
cursor.execute("SELECT ConfigData FROM #Configs WHERE ID = 1")
row = cursor.fetchone()
config = json.loads(row.ConfigData)
print(config["name"])  # 'Alice'

Használd a Microsoft SQL JSON funkciókat

Használd a Microsoft SQL JSON funkcióit, hogy közvetlenül lekérdezésekben parcellázd és szűrd a JSON adatokat, nem kliens kódban.

import json

data = {"name": "Alice", "scores": [95, 87, 91], "active": True}

cursor.execute("""
    CREATE TABLE #Configs (
        ID INT IDENTITY(1,1) PRIMARY KEY,
        ConfigData NVARCHAR(MAX)
    )
""")
cursor.execute(
    "INSERT INTO #Configs (ConfigData) VALUES (%(data)s)",
    {"data": json.dumps(data)}
)
conn.commit()

cursor.execute("""
    SELECT JSON_VALUE(ConfigData, '$.name') AS Name
    FROM #Configs
    WHERE JSON_VALUE(ConfigData, '$.active') = 'true'
""")
for row in cursor:
    print(row.Name)  # 'Alice'

Használja LIKE mintás párosításhoz, vagy engedélyezze a teljes szöveges indexet a fejlettebb szövegkereséshez.

Teljes szöveges lekérdezések

A LIKE vadkártyás mintákat tartalmazó operátor egyszerű alternatívát kínál a teljes szöveges kereséssel szemben, ha teljes szöveges index nem elérhető.

# Using CONTAINS (requires full-text index on the table)
cursor.execute("""
    SELECT JobTitle FROM HumanResources.Employee
    WHERE JobTitle LIKE %(search)s
""", {"search": "%Engineer%"})

# Pattern-based search as an alternative to full-text
cursor.execute("""
    SELECT Name FROM Production.Product
    WHERE Name LIKE %(search)s
""", {"search": "%Mountain%"})

Bevált gyakorlatok

Ezeket az irányelveket alkalmazzuk a string adatok helyesen kezelésére a nyelvek és kódolások között.

Használd nvarchart nemzetközi adatokhoz

Ha nem vagy biztos benne, hogy egy oszlop tartalmaz-e Unicode-ot, használd nvarchar. A tárolási költség mérsékelék, és megakadályozza az adatvesztést a karakterátalakítás miatt.

Az alábbi példa mutatja a különbséget az Unicode oszlopok definiálása és az ASCII adatok között:

-- Good: supports any language
CREATE TABLE #UserProfile (
    Name NVARCHAR(100),
    Bio NVARCHAR(MAX)
);

-- Limited: ASCII/Latin only
CREATE TABLE #UserProfileAscii (
    Name VARCHAR(100),
    Bio VARCHAR(MAX)
);

Karakterlánc hosszának ellenőrzése

Ellenőrizd a string hosszát a Python-ban beadás előtt, hogy elkerüld a csonkítási hibákat, és értelmes hibaüzeneteket adj a felhasználóknak.

def safe_insert(cursor, name: str, max_length: int = 100):
    """Insert with length validation."""
    if len(name) > max_length:
        raise ValueError(f"Name exceeds {max_length} characters")
    
    cursor.execute(
        "INSERT INTO #UserProfile (Name) VALUES (%(name)s)",
        {"name": name}
    )

A bináris karakterláncokat külön kell kezelni

Különbséget kell tenni a szöveges stringek (Pythonstr, SQLnvarchar) és a bináris adatok (Python, SQLbytes) között, hogy elkerüld varbinarya kódolási problémákat.

binary_data = b'\x00\x01\x02'  # bytes - use varbinary
text_data = "Hello"            # str - use nvarchar