서버에 접속하기

PHP 드라이버 다운로드

이 가이드를 사용해 연결을 열고 PHP가 받는 값을 확인한 후 작업이 완료되면 연결을 해제하세요. 이 프로그램들은 로컬 또는 원격 SQL Server 테스트 데이터베이스에 대해 SQL Server 인증을 사용합니다. 비밀번호 없는 Azure 및 Fabric 연결의 경우 Connect to Azure SQL and Fabric SQL을 사용하세요.

SQLSRV는 서버 이름과 연결 옵션 연관 배열을 받습니다. PDO_SQLSRV PHP 데이터 객체(PDO)를 구현하며 데이터 소스 이름(DSN) 문자열, 별도의 자격 증명 인자, 그리고 PDO 속성 배열을 수용합니다. 두 모델 모두 Microsoft ODBC 드라이버 for SQL Server를 사용합니다. 한 API에서 작동하는 연결이 다른 API의 옵션 이름이나 PHP 유형을 교환 가능하게 만들지는 않습니다.

연결 전에

  1. 지원되는 PHP 런타임과 Microsoft ODBC 드라이버를 설치하고, 사용할 PHP 확장 프로그램을 불러오세요.
  2. 애플리케이션을 실행하는 PHP 프로세스를 확인하세요. php --ini을 실행하면 명령줄 구성을 찾을 수 있고 php -m을 실행하면 로드된 확장 기능을 나열할 수 있습니다. SQLSRV는 sqlsrv이(가) 필요합니다. PDO_SQLSRV는 PDO와 pdo_sqlsrv를 필요로 한다. 웹 서버는 터미널과는 다른 php.ini, 런타임 및 계정을 사용할 수 있습니다.
  3. 서버 주소, 데이터베이스 이름, 그리고 연결 권한이 있는 계정을 얻으세요. 데이터베이스 로그인이 모든 테이블에 자동으로 권한을 부여하는 것은 아닙니다.
  4. 네트워크 접근과 신뢰할 수 있는 서버 인증서를 설정하세요. 이 프로그램들은 암호화와 인증서 검증을 명시적으로 요청합니다. 인증서에 명시된 호스트 이름으로 연결하고, 인증서에 포함되지 않은 IP 주소로 대체하지 마세요.

이 변수들은 셸, 개발 도구, 호스팅 설정을 사용하여 PHP 프로세스 환경에서 설정하세요. 비밀번호 파일을 커밋하거나 환경 변수를 출력하지 마세요.

변수 Value
SQL_SERVER 서버 호스트 이름은 선택적으로 tcp:가 앞에 붙고 뒤에 ,<port>가 오는 형식입니다.
SQL_DATABASE 로그인 시 접근할 수 있는 기존 데이터베이스입니다.
SQL_USER SQL Server 로그인
SQL_PASSWORD 보호된 구성을 통해 제공되는 해당 로그인의 비밀번호

웹 요청 매개변수가 아닌 신뢰할 수 있는 애플리케이션 구성에서 서버 및 데이터베이스 설정을 읽으세요. PDO 예시에서는 그 설정들을 DSN에 넣습니다. 연결 키워드를 애플리케이션 관리 하에 두세요.

실제 데이터베이스 이름, 사용자 이름, 비밀번호를 환경 변수에 저장하고, 직접 중괄호를 추가하거나 중복으로 넣지 마세요. 두 PHP 확장 모두 SQLSRV 배열 옵션과 PDO 생성자 인자에 대해서도 ODBC 스타일의 이스케이프가 필요합니다: 닫는 중괄호를 두 배로 하고 값을 중괄호로 감싸는 것입니다. 각 프로그램은 이 값을 드라이버에 전달하기 전에 한 번씩 이 작업을 수행합니다. 외부 괄호는 값의 시작과 끝에 문자 그대로 중괄호를 보존하고, 데이터베이스 이름 안의 세미콜론이 PDO DSN 설정을 분리하지 않도록 합니다. 이 이스케이프는 Transact-SQL(T-SQL) 매개변수 바인딩과는 별개입니다.

SQLSRV로 열고, 쿼리하고, 닫기

이 프로그램을 connect-sqlsrv.php로 저장하고 php connect-sqlsrv.php를 실행하세요. 테이블을 생성하거나 데이터를 변경하지 않고 T-SQL 쿼리를 실행합니다. CharacterSet 문자 데이터를 위해 UTF-8을 선택하며; 데이터베이스의 열 유형이나 정렬은 변경하지 않습니다.

<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name before running this example.");
    }
    $config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}

$conn = sqlsrv_connect($config['SQL_SERVER'], [
    'Database' => $config['SQL_DATABASE'],
    'UID' => $config['SQL_USER'],
    'PWD' => $config['SQL_PASSWORD'],
    'Encrypt' => true,
    'TrustServerCertificate' => false,
    'LoginTimeout' => 30,
    'CharacterSet' => 'UTF-8',
]);
if ($conn === false) {
    throw new RuntimeException(print_r(sqlsrv_errors(), true));
}

$stmt = null;
try {
    $sql = "SELECT CAST(42 AS int) AS Value, N'caf' + NCHAR(233) AS Label, "
        . "CAST(NULL AS int) AS Missing";
    $stmt = sqlsrv_query($conn, $sql, [], ['QueryTimeout' => 30]);
    if ($stmt === false) {
        throw new RuntimeException(print_r(sqlsrv_errors(), true));
    }
    $row = sqlsrv_fetch_array($stmt, SQLSRV_FETCH_ASSOC);
    if ($row === false) {
        throw new RuntimeException(print_r(sqlsrv_errors(), true));
    }
    if ($row !== ['Value' => 42, 'Label' => "caf\u{00e9}", 'Missing' => null]) {
        throw new RuntimeException('Unexpected SQLSRV values or PHP types.');
    }
    echo json_encode($row, JSON_THROW_ON_ERROR), PHP_EOL;
} finally {
    if (is_resource($stmt)) {
        sqlsrv_free_stmt($stmt);
    }
    sqlsrv_close($conn);
}

예상 출력:

{"Value":42,"Label":"caf\u00e9","Missing":null}

연결과 구문은 PHP 리소스이며, sqlsrv_* 함수에 전달하는 핸들입니다. 양쪽 손잡이 중 하나를 사용하기 전에 false를 확인하세요. 실패 직후 sqlsrv_errors()을 즉시 가져오세요. 나중에 SQLSRV 호출이 오류 수집을 대체할 수 있기 때문입니다.

SQLSRV_FETCH_ASSOC 열명을 키로 사용하는 연관 배열을 반환합니다. SQLSRV_FETCH_NUMERIC 0 기반 숫자 키를 반환합니다; 기본값 SQLSRV_FETCH_BOTH 에는 두 형태가 모두 포함됩니다. 에 대 null 해서는 sqlsrv_fetch_array()행이 더 이상 없음을 의미하고, false 오류를 의미합니다. 행 안에 있는 SQL NULL 은 PHP null입니다; 그렇다고 행이 빠진 것은 아닙니다. 이 값들을 구분할 때 ===을 사용하세요.

PDO_SQLSRV로 열고, 쿼리하고, 닫아요

이 별도의 프로그램을 connect-pdo.php로 저장하고 같은 환경에서 실행 php connect-pdo.php 하세요. sqlsrv: PDO_SQLSRV 선택하며, PHP의 일반적인 PDO_ODBC 드라이버가 아닙니다.

<?php
$config = [];
foreach (['SQL_SERVER', 'SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $value = getenv($name);
    if ($value === false || $value === '') {
        throw new RuntimeException("Set $name before running this example.");
    }
    $config[$name] = $value;
}
foreach (['SQL_DATABASE', 'SQL_USER', 'SQL_PASSWORD'] as $name) {
    $config[$name] = '{' . str_replace('}', '}}', $config[$name]) . '}';
}
$server = $config['SQL_SERVER'];
$database = $config['SQL_DATABASE'];
$pdo = new PDO(
    "sqlsrv:Server=$server;Database=$database;Encrypt=true;"
    . "TrustServerCertificate=false;LoginTimeout=30",
    $config['SQL_USER'],
    $config['SQL_PASSWORD'],
    [
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8,
    ]
);

$stmt = null;
try {
    $sql = "SELECT CAST(42 AS int) AS Value, N'caf' + NCHAR(233) AS Label, "
        . "CAST(NULL AS int) AS Missing";
    $stmt = $pdo->prepare($sql, [PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 30]);
    $stmt->execute();
    $row = $stmt->fetch();
    if ($row !== ['Value' => '42', 'Label' => "caf\u{00e9}", 'Missing' => null]) {
        throw new RuntimeException('Unexpected PDO_SQLSRV values or PHP types.');
    }
    echo json_encode($row, JSON_THROW_ON_ERROR), PHP_EOL;
} finally {
    $stmt = null;
    $pdo = null;
}

예상 출력:

{"Value":"42","Label":"caf\u00e9","Missing":null}

PDO_SQLSRV는 기본적으로 이 int 열을 PHP 문자열로 반환합니다. 지원되는 숫자 열에 대해 PHP 숫자 타입을 요청하려면 true를 PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE로 설정하세요. decimal 값에 대해 PHP 캐스팅을 무분별하게 사용하지 마세요; 부동소수점 변환은 정밀도를 잃을 수 있습니다.

PDO 속성은 연결 또는 statement 객체에 설정된 것입니다. PDO::ATTR_ERRMODE와 함께 PDO::ERRMODE_EXCEPTION를 사용하면 데이터베이스 작업 실패 시 PDOException가 발생합니다. 연결 생성은 그 설정과 상관없이 실패 시 예외를 발생시킵니다. PDO::FETCH_ASSOC 는 이름 있는 키를 주고, PDO::FETCH_NUM 는 0기반의 숫자 키를 제공하며, PDO::FETCH_BOTH 두 가지 모두를 제공합니다. fetch()는 결과 끝에 false를 반환합니다. 한 행 내 SQL NULL 값은 PHP null로 유지됩니다.

이 명령줄 프로그램은 실패 시 실행을 중지합니다. 웹 애플리케이션에서는 요청을 처리하는 코드에서 예외를 잡아냅니다. 보호 로그에 진단 세부사항을 기록하고 일반적인 오류 응답을 반환합니다. 브라우저로 sqlsrv_errors(), 예외 추적, 연결 문자열 또는 토큰을 보내지 마세요.

인증 모드 선택

모드 사용 목적 보십시오
SQL Server 인증 Microsoft Entra ID를 사용할 수 없는 경우의 온-프레미스 SQL Server, 컨테이너 및 Azure SQL SQL Server 인증을 이용한 연결
통합 인증 (연결 설정에 사용자 이름이나 비밀번호 없음) Windows 자격 증명 또는 Kerberos에 맞게 설정된 Linux/macOS 클라이언트 Windows 인증로 연결해
Microsoft Entra ID (Authentication 또는 AccessToken 키워드) Microsoft Entra ID용으로 구성된 Azure SQL 및 Fabric SQL 대상 Microsoft Entra 인증을 사용하여 연결

SQL 인증의 경우, SQLSRV는 연결 옵션 배열에 PWD와 UID를 사용합니다. PDO_SQLSRV는 사용자 이름과 비밀번호를 DSN 키워드가 아니라 new PDO()의 두 번째와 세 번째 인수로 받습니다. 액세스 토큰의 경우, SQLSRV는 AccessToken를 options 배열에서 받고, PDO_SQLSRV는 이를 DSN에서 받습니다.

사용자 이름, 비밀번호, Authentication, AccessToken를 생략하면 두 드라이버 모두 Trusted_Connection=Yes를 사용하여 ODBC에 통합 인증을 요청합니다. 리눅스와 macOS에서는 유효한 Kerberos 티켓과 ODBC 통합 인증 구성이 필요합니다. 원격 서버에 임의의 로컬 계정 접근 권한을 주지 않습니다.

연결과 그 문장을 구성하세요

연결 설정은 열리는 세션에 적용됩니다. 명령문 설정은 특정 쿼리에 적용됩니다. 애플리케이션이 기본값 외에 다른 값이 필요할 때 타임아웃과 결과 유형을 명시적으로 설정하세요.

Purpose SQLSRV PDO_SQLSRV 동작 소유자
엔드포인트와 데이터베이스 서버 인수와 Database 옵션. Server 그리고 Database DSN 키워드가 있습니다. ODBC와 SQL 타겟.
SQL 자격 증명 UID 그리고 PWD 선택지들. Constructor 사용자 이름과 비밀번호 인수. 확장 자격 증명 처리 및 서버 인증.
"Microsoft Entra" 인증 Authentication 선택지, 아니면 별도의 AccessToken 선택지. Authentication 또는 AccessToken DSN 키워드로, 외부 토큰의 자격 증명은 생략되었습니다. ODBC 인증; 애플리케이션은 외부 토큰을 획득합니다.
Encryption Encrypt => true; Encrypt=true DSN에서 ODBC 교통 보안.
인증서 유효성 검사 TrustServerCertificate => false; DSN에서 TrustServerCertificate=false ODBC와 운영체제의 인증서 신뢰 구성.
연결 설정 타임아웃 LoginTimeout 연결 옵션(초 단위). LoginTimeout DSN 키워드, 몇 초 만에. ODBC. SQL 문 실행 시간 초과 때문이 아닙니다.
쿼리 시간 제한 QueryTimeout 몇 초 만에 진술 옵션을 선택했습니다. PDO::SQLSRV_ATTR_QUERY_TIMEOUT, 연결 또는 문에 대해 말이다. 확장 및 ODBC 문 처리.
문자 인코딩 CharacterSet => 'UTF-8' 연결 옵션. PDO::SQLSRV_ATTR_ENCODING => PDO::SQLSRV_ENCODING_UTF8; PHP 확장 프로그램 변환. PDO_SQLSRV 기본적으로 UTF-8을 사용하며; SQLSRV는 시스템 인코딩을 기본값으로 사용합니다.
날짜 및 시간 객체 ReturnDatesAsStrings는 기본적으로 false이며, 날짜와 시간 열은 DateTime 객체를 반환합니다. 기본값은 문자열이며, 객체를 요청하려면 PDO::SQLSRV_ATTR_FETCHES_DATETIME_TYPE를 사용합니다. PHP 확장 프로그램 형식 변환.
다중 활성 결과 집합 (MARS) MultipleActiveResultSets 연결 옵션. MultipleActiveResultSets DSN 키워드. ODBC 및 타겟 지원. 두 확장 프로그램 모두 기본적으로 활성화되어 있습니다; Fabric의 Warehouse에서는 비활성화하세요.
유휴 상태 복구 ConnectRetryCount 및 ConnectRetryInterval 연결 옵션 같은 DSN 키워드입니다. ODBC. 임의의 애플리케이션 작업을 다시 시도하지 않습니다.

키워드, 허용 값, 기본 설정의 전체 목록은 연결 옵션을 참조하세요. PDO DSN에 QueryTimeout, PDO:: 또는 CharacterSet 상수 이름을 넣지 마세요.

연결 수명 관리

요청이나 작업이 데이터베이스 작업이 필요할 때 연결을 열어보세요. 요청이나 작업 내내 이를 재사용한 뒤, 완료되면 이를 해제하세요. 매 줄마다 연결했다가 끊지 마세요. 장기 실행 작업자라면, 다음 작업을 수락하기 전에 statement를 해제하고 각 거래를 완료하세요.

SQLSRV는 연결을 종료하면 연관된 문을 닫습니다. 명시적으로 더 일찍 명시적으로 문장을 해제하면 연결을 종료하지 않고 자원을 해제합니다. PDO의 경우, 할당하면 $pdo = null 해당 변수의 참조만 제거됩니다. 변수 PDOStatement 나 다른 변수는 여전히 연결을 유지할 수 있습니다. 그 참조들도 공개하세요. closeCursor() 보류 중인 결과를 해제하여 문을 재사용할 수 있게 합니다; 연결 종료 방식은 아닙니다.

두 API 모두 자동 커밋 모드에서 시작합니다: 성공적인 명령문은 별도의 애플리케이션 커밋 없이 커밋되며, 트랜잭션을 시작하는 경우를 제외하면 커밋됩니다. 함께 성공하거나 실패해야 하는 쓰기 그룹의 경우, 를 $pdo->beginTransaction()사용하여 sqlsrv_begin_transaction() 명시적으로 커밋 또는 롤백을 수행합니다. 미해결 트랜잭션이 있는 연결을 종료하는 것은 커밋이 아니라 롤백을 시도합니다. 트랜잭션 정책을 구현하는 데 셧다운 정리에 의존하지 마세요. 완전한 예시는 트랜잭션 수행을 참조하세요.

PHP 연결 핸들을 해제한다고 해서 반드시 물리적 네트워크 연결이 종료되는 것은 아닙니다. ODBC 풀링은 재사용을 위해 이를 보존할 수 있습니다. 풀링이 PHP 자원을 무기한 유지해야 하는 이유는 아니며, PDO_SQLSRV 지원 PDO::ATTR_PERSISTENT => true하지 않습니다. 플랫폼별 풀링 구성에 대해서는 연결 풀링을 참조하세요.

가이드를 SQL 타겟에 적용하세요

핸들, 페치, 정리 패턴은 지원되는 SQL 타겟의 두 확장 모두에 적용됩니다. 연결 엔드포인트, 인증, 네트워크 접근, SQL 기능은 다양합니다.

목표/타겟 각색
SQL Server 이 프로그램들은 SQL 로그인을 사용합니다. 통합 인증은 PHP 프로세스 ID를 구성할 때 또 다른 선택지입니다.
Azure SQL 데이터베이스 논리 서버 호스트 이름과 명시적인 데이터베이스를 사용하세요. 이 프로그램들에서는 SQL 자격 증명보다는 Microsoft Entra 인증을 선호하세요.
Azure SQL Managed Instance(애저 SQL 매니지드 인스턴스) 인스턴스 엔드포인트와 그 네트워크 접근 요구사항을 활용하세요. 개인 엔드포인트가 워크스테이션에서 접근 가능하다고 가정하지 마세요.
Azure Synapse Analytics SQL 풀 엔드포인트를 사용하고 객체를 생성하거나 수정하는 쿼리를 적응하기 전에 T-SQL 지원을 확인하세요.
Microsoft Fabric의 SQL 데이터베이스 데이터베이스 연결 정보와 Microsoft Entra 인증을 활용하세요. SQL 분석 엔드포인트를 대체하지 마세요.
Microsoft Fabric의 창고 웨어하우스 엔드포인트와 데이터베이스, Microsoft Entra 인증 및 MultipleActiveResultSets=false을 사용하세요.

서비스별 설정에 대해서는 Azure 및 Fabric 연결을 참조하세요.

연결 문제 해결

실패한 단계부터 시작하세요. 전송 제어 프로토콜(TCP) 검사가 성공했다고 해서 인증이나 인증서 검증이 성공했다는 증거는 아닙니다.

증상 수표
Call to undefined function sqlsrv_connect() 실행 중인 PHP 프로세스가 로드 sqlsrv되지 않았습니다. 시작 경고와 해당 php.ini을 확인하세요.
PDO 보고 could not find driver pdo_sqlsrv이(가) 해당 프로세스에 로드되어 있고 sqlsrv이(가) PDO::getAvailableDrivers()에 나타나는지 확인합니다.
ODBC 드라이버를 찾을 수 없습니다 Microsoft ODBC 드라이버를 설치하고 드라이버의 등록 상태 및 아키텍처를 확인하세요. PHP 확장 프로그램을 설치한다고 해서 ODBC가 자동으로 설치되는 것은 아닙니다.
연결 타임아웃 또는 서버를 찾지 못했습니다 서버 이름, 포트, 이름 해석, 라우팅, 방화벽 규칙, SQL Server가 TCP를 수신 대기하는지 확인하세요.
인증서 체인 또는 호스트 이름 검증 실패 올바른 신뢰 체인을 설치하고 인증서의 호스트 이름을 사용하세요. TrustServerCertificate=true를 프로덕션 수정으로 취급하지 마세요.
로그인 실패 또는 데이터베이스를 열 수 없습니다 인증 모드, 데이터베이스 이름, 로그인/사용자 매핑, 권한 등을 확인하세요. 자격 증명을 생략하면 통합 인증이 요청됩니다; SQL 인증을 선택하지 않습니다.
터미널에서는 성공하지만 웹 요청은 실패합니다 PHP 런타임, 로드된 확장, 프로세스 ID, 환경 변수, 네트워크 접근을 비교해 보세요. 설정 정보가 포함된 공개 phpinfo() 페이지를 노출하지 마세요.
이후 작업은 닫힌 핸들에서 실패합니다 모든 문 작업 내내 연결을 유지하세요. 연결을 닫은 후 새 연결을 생성하세요; 오래된 핸들은 스스로 열리지 않습니다.

기타 관련 문서