mssql-python으로 데이터를 검색하기

mssql-python 드라이버는 여러 페치 메서드, 행 접근 패턴, 쿼리 결과 검색을 위한 커서 내비게이션 기능을 제공합니다.

가져오기 방법

SELECT 쿼리를 실행한 후에는 fetch 메서드를 사용하여 결과를 가져오세요.

fetchone()

한 행을 반환하거나, None 더 이상 사용할 수 있는 행이 없을 경우:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product")

row = cursor.fetchone()
while row:
    print(f"{row.ProductID}: {row.Name} - ${row.ListPrice}")
    row = cursor.fetchone()

페치매니()

행 목록을 반환합니다. cursor.arraysize 기본 배치 크기 제어(기본값: 1):

cursor.execute("SELECT * FROM Production.Product")
cursor.arraysize = 100  # Fetch 100 rows at a time

while True:
    rows = cursor.fetchmany()
    if not rows:
        break
    for row in rows:
        print(row.Name)

크기를 직접 지정할 수도 있습니다:

rows = cursor.fetchmany(50)  # Fetch up to 50 rows

fetchall()

남은 모든 행을 리스트로 반환합니다:

cursor.execute("SELECT * FROM Production.Product WHERE Color = 'Black'")
rows = cursor.fetchall()

print(f"Found {len(rows)} products")
for row in rows:
    print(row.Name)

fetchval()

첫 번째 행의 첫 번째 열을 반환하여 스칼라 쿼리에 유용합니다.

count = cursor.execute("SELECT COUNT(*) FROM Production.Product").fetchval()
print(f"Total products: {count}")

max_price = cursor.execute("SELECT MAX(ListPrice) FROM Production.Product").fetchval()
print(f"Highest price: ${max_price}")

행 액세스 패턴

이 클래스는 Row 다중 접근 패턴을 지원합니다.

인덱스 접근

위치로 열에 액세스(0부터 시작):

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()

product_id = row[0]
name = row[1]
price = row[2]

속성 접근

이름별로 열에 접근하기:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()

product_id = row.ProductID
name = row.Name
price = row.ListPrice

소문자 열명

소문자 속성 이름을 전역적으로 활성화하기:

import mssql_python

settings = mssql_python.get_settings()
settings.lowercase = True

cursor.execute("SELECT ProductID, Name FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()
print(row.productid, row.name)  # Lowercase access
settings.lowercase = False  # Restore default

반복

행은 값에 대한 반복을 지원합니다:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")
row = cursor.fetchone()

for value in row:
    print(value)

커서 반복 처리

커서를 직접 순회하며 행을 처리합니다:

cursor.execute("SELECT * FROM Production.Product")

for row in cursor:
    print(row.Name)

이 패턴은 반복적으로 부르 fetchone() 는 것과 같습니다.

열 메타데이터

열 정보 접근은 다음을 통해 cursor.description이루어집니다:

cursor.execute("SELECT ProductID, Name, ListPrice FROM Production.Product WHERE ProductID < 5")

for col in cursor.description:
    name, type_code, display_size, internal_size, precision, scale, null_ok = col
    print(f"Column: {name}, Type: {type_code}, Nullable: {null_ok}")

행 수

속성은 cursor.rowcount 다음을 나타냅니다:

  • SELECT의 경우: execute() 이후 가져오기가 시작될 때까지 -1을 반환합니다. 가져오기를 시작하면 지금까지 가져온 행의 누적 개수를 반영합니다.
  • INSERT/UPDATE/DELETE의 경우: 영향을 받은 행 수.
cursor.execute("SELECT * FROM Production.Product")
print(f"Rows returned: {cursor.rowcount}")

cursor.execute("CREATE TABLE #PriceUpd (Name NVARCHAR(50), Price DECIMAL(10,2), CategoryID INT)")
cursor.execute("INSERT INTO #PriceUpd VALUES ('A',10,1),('B',20,1),('C',30,2)")
cursor.execute("UPDATE #PriceUpd SET Price = Price * 1.1 WHERE CategoryID = 1")
print(f"Rows updated: {cursor.rowcount}")

커서 이동

skip()

가져오지 않고 행 건너뛰기:

cursor.execute("SELECT * FROM Production.Product ORDER BY ProductID")
cursor.skip(10)  # Skip first 10 rows
row = cursor.fetchone()  # Returns 11th row

스크롤()

커서 위치를 앞으로 이동:

cursor.execute("SELECT * FROM Production.Product ORDER BY ProductID")

# Move forward 5 rows from current position
cursor.scroll(5, mode='relative')

row = cursor.fetchone()

비고

드라이버는 양수로만 mode='relative' 지지합니다. 드라이버가 전방 전용 커서를 사용하므로 절대 위치 지정과 뒤로 스크롤을 수행하면 NotSupportedError 예외가 발생합니다.

행 번호

현재 위치를 추적하세요:

cursor.execute("SELECT * FROM Production.Product")

print(f"Initial position: {cursor.rownumber}")  # -1 (before first fetch)

row = cursor.fetchone()
print(f"After fetchone: {cursor.rownumber}")    # 0 (first row fetched)

다중 결과 집합

여러 결과 세트를 처리하는 데 사용 nextset() :

cursor.execute("""
    SELECT * FROM Production.Product WHERE Color = 'Black';
    SELECT * FROM Production.ProductCategory;
    SELECT COUNT(*) FROM Production.Product;
""")

# First result set
products = cursor.fetchall()
print(f"Products: {len(products)}")

# Move to second result set
if cursor.nextset():
    categories = cursor.fetchall()
    print(f"Categories: {len(categories)}")

# Move to third result set
if cursor.nextset():
    count = cursor.fetchval()
    print(f"Total count: {count}")

대규모 결과 집합

큰 결과 집합의 경우, 메모리 관리를 위해 배치 단위로 행을 처리하세요:

def process_batch(rows):
    # Example: print each row. Replace with your own logic.
    for row in rows:
        print(row)

cursor.execute("SELECT * FROM LargeTable")
cursor.arraysize = 1000

while True:
    rows = cursor.fetchmany()
    if not rows:
        break

    process_batch(rows)
    print(f"Processed {cursor.rownumber} rows so far")

컨텍스트 관리자

컨텍스트 관리자를 사용해 자동 리소스 정리를 하세요:

with mssql_python.connect(connection_string) as conn:
    with conn.cursor() as cursor:
        cursor.execute("SELECT * FROM Production.Product")
        for row in cursor:
            print(row.Name)
# Cursor and connection closed automatically

모범 사례

  • 전체를 메모리에 로드하지 않으려면 대량의 결과에는 fetchmany()를 사용하세요.
  • 서버 리소스를 해제하려면 작업이 끝나면 커서를 닫으세요.
  • 더 읽기 쉬운 코드를 위해 열명(속성 접근)을 사용하세요.
  • 확인 rowcount 데이터 수정 문 후에.
  • 열이 nullable일 때는 값을 명시적으로 처리하세요None.