Dizeleri ve Unicode'u işleme

Microsoft SQL, mssql-python sürücüsünün Python str nesnelerine eşlediği birden fazla dizi türü sağlar. Temel karar, (Unicode olmayan) veya varchar (Unicode) mi kullanılacağıdır nvarchar :

  • Verilerinizde herhangi bir dilde isimler, adresler veya kullanıcı tarafından oluşturulan içerik gibi ASCII dışındaki karakterler bulunabileceği durumlarda kullanın nvarchar .
  • Veriler tamamen ASCII (kodlar, tanımlayıcılar, e-posta adresleri) olduğunda ve depolama kaydı yapmak istediğinizde kullanın varchar . varchar her karakter için 1 bayt kullanır; nvarchar Karakter başına 2 bayt kullanıyor.
SQL Türü Unicode Maksimum Uzunluk Python Türü
char(n) Hayır 8,000 str
varchar(n) Hayır 8,000 str
varchar(max) Hayır 2GB str
nchar(n) Evet 4,000 str
nvarchar(n) Evet 4,000 str
nvarchar(max) Evet 2GB str
text Hayır 2 GB (kullanımdan çıktı) str
ntext Evet 2 GB (kullanımdan çıktı) str

Temel dize işlemleri

Sürücü, tüm Microsoft SQL dizi türlerini Python str nesnelerine eşler.

Dizeleri ekle ve al

Veritabanından dizi verilerini güvenli bir şekilde eklemek ve almak için parametrizeli sorgular kullanın.

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'

Özel karakter içeren dizeler

Dizelerdeki tırnak noktaları, açı parantezleri ve diğer özel karakterleri parametrizlenmiş sorgular kullanarak işleyin.

# 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 desteği

Metni herhangi bir dilde depolamak ve geri almak için nvarchar sütunlarını ve Python str kullanın.

Unicode metni sakla

Unicode içeriğini Python dizileri parametrizlenmiş sorgulara geçirerek ekleyin; sürücü bunları nvarchar sütunları için UTF-16LE olarak kodlar.

# 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 你好 مرحبا שלום 🎉'

Farklı yazı sistemlerinde Unicode

nvarchar sütunlarını ve toplu eklemeleri kullanarak tek bir tabloda birden çok dili ve yazı sistemini destekleyin.

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

Unicode için nvarchar sütunlarını garanti edin

Verileriniz ASCII olmayan karakterler içerebilirse, sütunları varchar yerine her zaman nvarchar olarak tanımlayın.

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

Tel uzunluğu konularında dikkate alınan unsurlar

Veri uzunluklarınızın tutarlılığına göre sabit uzunluklu ve değişken uzunluklu türler arasında seçim yapın.

Sabit ve değişken uzunluk arasındaki fark

Microsoft SQL'de char(n), değerleri bildirilen uzunluğa kadar sondaki boşluklarla doldurur. Bu dolgu, değişken uzunluklu veriler için depolama alanını israf eder ancak ülke kodları gibi sabit genişlikli sütunlar için performansı artırabilir. Çoğu dize sütunu için varchar(n) kullanın.

Aşağıdaki örnek, dolgulu ve dolgusuz sütunların veri alımını nasıl yönettiğini gösterir:

# 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

Takip boşluklarını tutun

Sabit uzunluktaki karakter sütunlarından veri alırken, Microsoft SQL Server tarafından eklenen dolgu alanlarını kaldırmak için kullanınrstrip().

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

Büyük dizeler (MAX türleri)

Ve nvarchar(max) türleri, varchar(max) büyük metin belgeleri, JSON veya XML içeriği depolamak için ideal olan 2 GB'a kadar dizileri destekler.

# 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

Dize karşılaştırması ve derleme

Microsoft SQL dizisi karşılaştırma davranışı, veritabanı veya sütundaki derleme setine bağlıdır.

Büyük/küçük harfe duyarlı

Microsoft SQL dizisi karşılaştırması derlemeye bağlıdır. Varsayılan olarak, çoğu veritabanı büyük/küçük harfe duyarsız harmanlama kullanır, ancak bunu COLLATE yan tümcesiyle geçersiz kılabilirsiniz.

# 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 kalıp eşleştirme

Joker karakterli LIKE operatörü kullanarak dize desenlerini arayın; özel karakterlerden kaçış parantez gösterimiyle literalleri eşleştirin.

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

Kodlama konuları

Kodlama davranışı, Microsoft SQL sütun tipine ve kaynak derlemesine bağlıdır.

Kodlama varsayımları ve Unicode varsayılanları

Sürücü, mssql-python Microsoft SQL sütun tipine göre otomatik olarak kodlamayı gerçekleştirir. Varsayılan olarak, dize parametreleri nvarchar sütunları için UTF-16LE olarak ve varchar sütunları için veritabanı derlemesine göre gönderilir:

Sütun türü Tel kodlama Python sonucu
nvarchar, nchar, ntext UTF-16LE str (sürücü tarafından çözülüyor)
varchar, char, text Veritabanı veya sütun derleme kodlaması str (sürücü tarafından kaynak kodlaması kullanılarak çözülür)

Python dizileri her zaman dahili olarak Unicode'dur. Bir str parametreyi geçtiğinizde, sürücü onu hedef sütun tipi için kodlar. Varsayılan olarak, sürücü dizi parametrelerini (Unicode) olarak nvarchar gönderir; bu da veritabanı derlemesinden bağımsız olarak karakterlerin korunmasını sağlar. Sütunlar için varchar , UTF-8 yalnızca veritabanı veya sütun UTF-8 destekli bir derleme kullandığında geçerlidir.

Eğer sütununuz ise varchar ve sütun tipine tam olarak uydurmak için Unicode dışı veri göndermeniz gerekiyorsa (örneğin, örtük dönüşüm uyarılarından kaçınmak için), varsayılan olanı geçersiz kılmak için kullanın setinputsizes() :

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

Çoğu uygulama için varsayılan davranış doğrudur. Sadece sorgu planlarında örtük dönüşüm uyarıları gördüğünde veya belirli varchar bir derlemeyi eşleştirmeniz gerektiğinde geçersiz kılın.

Bağlantı kodlaması

mssql-python sürücüsü, bağlantı için Microsoft SQL Server sürümü ve yapılandırmasına göre otomatik olarak kodlamayı yönetir. Python dizileri Unicode olduğundan, sürücü onları hedef veri tipine uygun şekilde (UTF-8 veya UTF-16) kodlar. Bağlantı kodlamasını manuel olarak yapılandırmanıza gerek yok.

VARCHAR sütunları ve miras derlemeleri

Windows-1252 (CP1252) derlemelerine sahip veritabanları, örneğin Latin1_General_CI_AS, genişletilmiş Latin karakterleri (örneğin, , ve vurgulu karakterler) varchar CP1252 kodlamasını kullanarak sütunlarda depolar. Sürücü bu karakterleri tüm platformlarda doğru şekilde çözer.

Bu fark, platformlar arası dağıtımlar için önemlidir: Windows'ta doğru okunan aynı varchar veriler Linux'ta da doğru okunur ve özel yapılandırma gerektirmez.

# 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

Şemanız izin veriyorsa, varchar sütunlarını nvarchar biçimine taşımak, kodlama belirsizliğini tamamen ortadan kaldırır ve tüm Unicode karakterlerini destekler.

Dosya kodlama

Veritabanına eklenecek dosyaları okurken, Unicode içeriğini korumak için uygun kodlamayı belirtin.

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

Yaygın dize işlemleri

Bu örnekler, hem Python hem de SQL'de yaygın dize işleme kalıplarını kapsar.

Birleştirme

Dizeleri, eklemeden önce Python’da ya da sunucuda SQL’in dize operatörlerini kullanarak birleştirebilirsiniz.

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

Dize biçimlendirme

Python'da formatlama uygulayın; kullanıcılara göstermeden önce para birimi, dolgu veya hizalama ile dizileri gösterin.

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 ile boş dizi karşılaştırıldığında

Microsoft SQL, NULL ve boş diziyi ('') farklı değerler olarak ele alır. NULL "bilinmeyen" anlamına gelirken, boş dizelik "boş olduğu bilinen" anlamına gelir. Başvurunuz için bir konvansiyon seçin ve tutarlı olun. Çoğu uygulama, eksik isteğe bağlı alanlar için NULL kullanır.

Aşağıdaki örnek, NULL ile boş diziyi nasıl ayırt edeceğinizi gösterir:

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

Kırpma işlemleri

Python'un dize yöntemlerini kullanarak veritabanından alınan değerlerin başındaki, sonundaki veya her ikisindeki boşlukları kaldırın.

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 dizi veri

JSON belgelerini nvarchar(max) sütunlarında sakla ve Microsoft SQL'in JSON fonksiyonlarıyla sorgula.

JSON'u nvarchar olarak sakla

Python sözlüklerini JSON dizelerine seri hale getirin ve nvarchar sütunlarına yerleştirin; bunları geri alın ve yeniden Python nesnelerine dönüştürün.

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'

Microsoft SQL JSON fonksiyonlarını kullanın

Microsoft SQL'nin JSON fonksiyonlarını kullanarak JSON verilerini istemci kodunda değil, doğrudan sorgularda ayrıştırın ve filtreleyin.

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'

Desen eşleştirme için kullanın LIKE veya daha gelişmiş metin araması için tam metin indeksi etkinleştirin.

Tam metin sorgular

Joker karakter desenlerine sahip LIKE işleci, tam metin dizini olmadığında tam metin araması için doğrudan bir alternatif sunar.

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

En iyi uygulamalar

Bu yönergeleri, diller ve kodlamalar arasında dizi verilerini doğru şekilde işlemek için uygulayın.

Uluslararası veriler için nvarchar kullanın

Bir sütunun Unicode içerip içermeyeceğinden emin değilseniz, nvarchar. Depolama maliyeti mütevazı ve karakter dönüşümünden kaynaklanan veri kaybını önler.

Aşağıdaki örnek, Unicode ile sadece ASCII veri için sütun tanımlama arasındaki farkı göstermektedir:

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

Dizinin uzunluğunu doğrulama

Kesme hatalarını önlemek ve kullanıcılara anlamlı hata mesajları vermek için Python'da dizi uzunluğunu kontrol edin.

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

İkili dizeleri ayrı ayrı ele alın

Kodlama sorunlarından kaçınmak için metin dizeleri (Pythonstr, SQLnvarchar) ile ikili veri (Pythonbytes, SQL varbinary) arasında ayrım yapın.

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