Microsoft PHP for SQL Server 드라이버는 PHP 스크립트를 통해 Microsoft SQL 데이터베이스 엔진에서 데이터를 읽고 쓸 수 있는 PHP 확장 프로그램입니다. 두 확장 프로그램은 동일한 Microsoft ODBC Driver for SQL Server를 사용하지만, 서로 다른 PHP API와 드라이버별 옵션을 제공합니다:
-
SQLSRV는 SQL Server 기능에 맞춘 절차적 API(
sqlsrv_*함수)를 노출합니다. - PDO_SQLSRV는 PHP 데이터 객체(PDO) 인터페이스를 구현합니다. PDO 호출은 기존 데이터베이스 코드에 유지할 수 있지만, 데이터베이스를 전환하기 전에 쿼리와 드라이버별 설정을 검토하세요.
두 드라이버 모두 Azure SQL Database, Microsoft Fabric의 SQL 데이터베이스, Azure SQL Managed Instance, 그리고 Express 에디션을 포함한 지원되는 모든 SQL Server 버전 및 에디션에 연결할 수 있습니다. 두 드라이버 모두 PHP 스트림을 입력 매개변수로 받아들입니다. SQLSRV는 큰 이진 값과 문자 값을 스트림으로 가져오는 것을 지원합니다. PDO_SQLSRV가 동일한 출력 스트리밍 동작을 가진다고 가정하지 마세요.
시작점 선택
- 설치 상태를 확인하고 SQLSRV 또는 PDO_SQLSRV를 사용해 매개변수화된 쿼리를 실행하려면 Quickstart: Connect and Microsoft Drivers for PHP로 쿼리를 시작하세요.
- Linux나 macOS에 드라이버를 설치하려면 Linux 및 macOS 설치 튜토리얼부터 시작해 Microsoft Drivers for PHP for SQL Server를 다운로드하세요.
- 비밀번호 없는 인증으로 Azure SQL에 연결하려면 Microsoft Entra 인증 및 연결 옵션을 사용해 Connect를 시작하세요.
- 기존 앱을 일시적 장애에 대해 복원력 있게 만들려면 유휴 연결 복원력으로 이동하세요.
- SQLSRV와 PDO_SQLSRV 중에서 결정하려면 SQL Server PHP Microsoft 드라이버 개요와 실행 함수 비교를 참고하세요.
- 설치, 연결 또는 쿼리 문제를 진단하려면 문제 해결, 오류 및 경고 처리, 그리고 활동 기록으로 이동하세요.
- 기존 앱을 더 빠르게 하려면 Performance tuning으로 가세요.
Azure SQL 대한 프로덕션 기준
이 PDO_SQLSRV 예시는 환경 변수에서 서버와 데이터베이스를 읽고 관리 ID를 사용해 연결합니다. 데이터 소스 이름(DSN)을 생성하고 인증서 검증을 사용해 전송 계층 보안(TLS)을 활성화합니다. 이 값들은 웹 요청 매개변수가 아닌 신뢰할 수 있는 애플리케이션 구성에서 읽으세요. 데이터베이스에 신원 접근 권한을 부여한 후, 관리형 신원 엔드포인트가 있는 호스트에서 프로그램을 실행하세요.
헬퍼 함수는 나열된 오류가 발생하면 연결하거나 읽기 전용 쿼리를 실행하려고 최대 세 번까지 시도합니다. 시도 간격이 길어지는데, 이는 '지수적 백오프(exponential backoff)'라고 불리는 재시도 패턴입니다. 쿼리 오류가 새로운 연결을 필요로 하면, 쿼리 헬퍼는 호출 코드에서 처리할 수 있도록 예외를 던집니다.
지원되는 PHP 버전, PDO_SQLSRV 확장 프로그램, SQL Server Microsoft ODBC 드라이버 18을 사용하세요. 지원되는 인증 값에 대해서는 Microsoft Entra 인증을 사용하여 연결 항목을 참조하세요. 애플리케이션 전용 재시도 정책을 설계하지 않고 쿼리 헬퍼를 쓰기나 다중 문 트랜잭션에 재사용하지 마세요: 오류가 항상 쓰기 작업이 커밋되었는지 알려주지는 않습니다.
<?php
declare(strict_types=1);
// Transient errors that require a fresh connection to recover. SQLSTATE values
// starting with '08' cover ODBC connection-established and connection-broken
// states (for example, 08001, 08S01).
const CONNECT_RETRY_SQLSTATE_PREFIX = '08';
// SQL Server error codes that are transient regardless of when they surface:
// 1205 (deadlock victim), 1222 (lock request timeout), and the Azure SQL
// throttling, mid-query failover, and "database not currently available"
// codes that arrive with SQLSTATE HY000.
const TRANSIENT_SERVER_ERROR_CODES = [1205, 1222, 40501, 40613, 40197, 10928, 10929, 49918];
// This read helper retries only the listed errors on the same connection.
// Other errors propagate; the caller must decide whether to reconnect.
const RETRYABLE_READ_ERROR_CODES = [1205, 1222, 40501, 10928, 10929];
/**
* Open a connection, retrying transient failures with exponential backoff.
*/
function connectWithRetry(string $dsn, array $options, int $maxAttempts = 3): PDO
{
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
try {
$pdo = new PDO($dsn, null, null, $options);
error_log(sprintf('connected on attempt %d/%d', $attempt, $maxAttempts));
return $pdo;
} catch (PDOException $e) {
$sqlstate = (string) $e->getCode();
$driverCode = isset($e->errorInfo[1]) ? (int) $e->errorInfo[1] : 0;
$isTransient = str_starts_with($sqlstate, CONNECT_RETRY_SQLSTATE_PREFIX)
|| in_array($driverCode, TRANSIENT_SERVER_ERROR_CODES, true);
if (!$isTransient || $attempt === $maxAttempts) {
error_log(sprintf('connect failed on attempt %d/%d: %s', $attempt, $maxAttempts, $e->getMessage()));
throw $e;
}
$delay = 2 ** ($attempt - 1);
error_log(sprintf('connect attempt %d hit transient %s/%d; retrying in %d seconds', $attempt, $sqlstate, $driverCode, $delay));
sleep($delay);
}
}
throw new RuntimeException('connectWithRetry exhausted retries');
}
/**
* Retry the standalone read-only query for errors that allow connection reuse.
*/
function queryWithRetry(PDO $pdo, string $sql, array $params = [], int $maxAttempts = 3): PDOStatement
{
for ($attempt = 1; $attempt <= $maxAttempts; $attempt++) {
try {
$stmt = $pdo->prepare($sql);
$stmt->execute($params);
return $stmt;
} catch (PDOException $e) {
$driverCode = isset($e->errorInfo[1]) ? (int) $e->errorInfo[1] : 0;
$isTransient = in_array($driverCode, RETRYABLE_READ_ERROR_CODES, true);
if (!$isTransient || $attempt === $maxAttempts) {
error_log(sprintf('query failed on attempt %d/%d: %s', $attempt, $maxAttempts, $e->getMessage()));
throw $e;
}
$delay = 2 ** ($attempt - 1);
error_log(sprintf('query attempt %d hit transient code %d; retrying in %d seconds', $attempt, $driverCode, $delay));
sleep($delay);
}
}
throw new RuntimeException('queryWithRetry exhausted retries');
}
// Load endpoint details from application configuration. In Azure App Service,
// these can come from app settings or Key Vault-backed settings.
$server = getenv('SQL_SERVER') ?: null;
$database = getenv('SQL_DATABASE') ?: null;
if ($server === null || $database === null) {
throw new RuntimeException('Set SQL_SERVER and SQL_DATABASE in your application configuration.');
}
$databaseValue = '{' . str_replace('}', '}}', $database) . '}';
$dsn = sprintf(
'sqlsrv:Driver={ODBC Driver 18 for SQL Server};Server=%s;Database=%s;'
. 'Encrypt=true;TrustServerCertificate=false;'
. 'LoginTimeout=90;Authentication=ActiveDirectoryMsi;'
. 'ConnectRetryCount=5;ConnectRetryInterval=15;'
. 'MultiSubnetFailover=true;',
$server,
$databaseValue
);
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 30,
];
$pdo = connectWithRetry($dsn, $options);
$stmt = queryWithRetry($pdo, 'SELECT name FROM sys.databases WHERE database_id > ? ORDER BY name', [1]);
foreach ($stmt as $row) {
echo $row['name'], PHP_EOL;
}
이 설정들은 Azure SQL Database 장애 조치 그룹과 Azure SQL Managed Instance에 사용하세요.
Driver={ODBC Driver 18 for SQL Server}드라이버 발견에 의존하지 않고 ODBC 드라이버 18을 명시적으로 선택합니다. 예제를 실행하기 전에 설치하세요.SQL_DATABASE를 실제 데이터베이스 이름으로 설정하세요. 이 프로그램은 닫는 중괄호를 두 번 쓰고, 이름을 중괄호로 감싼 후 DSN에 넣습니다. 이스케이핑은 이름 내 특수 문자가 드라이버가 연결 설정을 읽는 방식을 바꾸지 않도록 막아줍니다.ConnectRetryCount및ConnectRetryInterval은 ODBC 유휴 연결 복원력을 제어합니다. 문의 쿼리 타임아웃은 실행 중 복구 시간의 상한을 정합니다. 샘플의 30초 쿼리 타임아웃 때문에 ODBC는 다섯 번의 재연결 시도를 모두 시도하기 전에 중단할 수 있습니다.LoginTimeout=90연결 설정을 제어하는 것이지, 복구 예산을 제어하는 것이 아닙니다. 애플리케이션 레벨 헬퍼는 선택된 서버 오류를 재시도하며; 쿼리 타임아웃을 재시도하거나 부분적으로 가져온 결과를 재생하지 않습니다.프로그램
error_log()호출과 함께 드라이버 기록을 활성화하세요. PDO_SQLSRV의 경우php.ini에서pdo_sqlsrv.log_severity을 설정하거나 런타임에ini_set()로 설정하세요. SQLSRV의 경우,LogSubsystems및sqlsrv_configure()를LogSeverity로 구성하세요. 자세한 내용은 기록 활동을 참조하세요.; php.ini - enable PDO_SQLSRV driver diagnostics alongside the application-level ; error_log() calls in the sample. Use 1 (errors) in production; -1 (all) is ; useful during triage but very chatty. [pdo_sqlsrv] pdo_sqlsrv.log_severity = 1사용자 할당 관리 신원의 경우, 해당 신원의 ID를 PDO의
$username인자()로 전달합니다.new PDO($dsn, $identityId, null, $options)Azure App Service 또는 Azure Container Instance에서 해당 식별자의 클라이언트 ID를 사용하세요; 그렇지 않으면 객체 ID를 사용하세요. PHP 드라이버는 이 동작을 Microsoft ODBC Driver for SQL Server에서 계승합니다; 자세한 내용은 ODBC 드라이버와 함께 Microsoft Entra ID 사용하기를 참조하세요. DSN에 사용자명을 삽입하는 대신 PDO 생성자의 사용자 이름 인수를 사용하세요.null를 사용자 인수로 전달하면(샘플에서와 같이) Azure 호스트의 시스템 할당 관리 ID가 선택됩니다. SQLSRV(절차적)의 경우, 연결 옵션 배열을 전달UID합니다.장애 조치 그룹 리스너, 가용성 그룹 리스너 또는 장애 조치 클러스터 인스턴스 엔드포인트에 연결할 때
MultiSubnetFailover=true를 설정하세요. 이 설정을 하면 단일 서브넷과 다중 서브넷 가용성 그룹 리스너 모두의 연결 성능이 향상됩니다. 자세한 내용은 고가용성 지원, 재해 복구를 참조하세요.읽기 스케일아웃이나 읽기 가능한 보조 장치를 위해 DSN에 추가
ApplicationIntent=ReadOnly하세요.SQL 서비스에서 제공하는 엔드포인트, 클라우드 전용 도메인을 포함해 사용하세요. 인증서 검증을 비활성화하기보다는 인증서 이름 불일치를 조사하세요. 해당 엔드포인트의 예상 인증서 이름을 알 때만 사용
HostNameInCertificate하세요.ODBC는 관리 신원 및 서비스 주체 인증을 위한 토큰을 획득합니다.
AccessToken를 사용하면 애플리케이션이 토큰을 획득해 드라이버에게 전달합니다; ODBC가 대신 토큰을 획득하지 않습니다. 자세한 내용은 ODBC 드라이버와 Microsoft Entra ID 사용을 참조하세요.연결 정보는 코드 밖에 두세요. 애플리케이션 설정 시스템에 저장하고, 비밀은 Azure Key Vault를 사용하세요.
SQLSRV에서는 배열에서 연결
sqlsrv_connect()옵션을 설정하세요. 반품 여부를false확인하고 점검sqlsrv_errors()한 후 재시도 여부를 결정하세요. 문장 타임아웃을 별도로 설정하세요QueryTimeout. 유휴 연결 복원력 은 애플리케이션 수준의 재시도 루프가 아니라 ODBC 재연결을 보여줍니다.재시도 도우미는
isset()로 보호되는$e->errorInfo[1]를 읽습니다.PDOException::$errorInfo는 로?array선언되고 기본값은null이므로 방어 검사는 드라이버0코드로 되돌아가고 SQLSTATE08접두사가 재시도 여부를 결정하게 합니다.
이 구성의 각 부분에 대한 자세한 내용은 다음을 참조하세요.
Azure SQL 일시적 오류 카탈로그는 일시적인 연결 오류 문제를 참조하세요.
주요 기능
- 두 가지 PHP API: SQLSRV는 절차적 기능을 제공합니다. PDO_SQLSRV는 PDO를 구현합니다. 확장 프로그램 중 하나 또는 둘 다 설치하세요.
- 광범위한 플랫폼 지원: Windows, Linux, macOS에서 실행되며 PHP 버전도 지원합니다.
-
암호화된 연결: 를 통한
Encrypt=trueTLS 암호화된 연결, 서버 인증서 검증은 로TrustServerCertificate제어됩니다. -
Microsoft Entra ID 인증: 관리형 신원, 서비스 주체, 그리고 Microsoft ODBC Driver for SQL Server를 통해 외부에서 획득한 접근 토큰을 관리합니다. 관리형 ID는 비밀번호가 없으며,
ActiveDirectoryServicePrincipal는 클라이언트 암호를 사용합니다. - Always Encrypted: 클라이언트에서 민감한 열을 암호화하고, 암호화된 데이터에 대한 지원 작업을 위한 안전한 엔클레이브를 제공합니다.
-
연결 복원성:
ConnectRetryCount및ConnectRetryInterval를 사용한 기본 제공 유휴 연결 재시도 기능. - PHP 스트림: 스트림 파라미터에서 큰 바이너리 및 문자 값을 두 API 중 하나로 전송할 수 있습니다. 스트림 검색에는 SQLSRV를 사용하세요.
-
풍부한 SQL Server 데이터 형식 지원: datetimeoffset, 테이블 반환 매개 변수, nvarchar, 그리고
PDO::SQLSRV_ENCODING_UTF8를 지원하는 유니코드.
Get started
| 조항 | 설명 |
|---|---|
| 시스템 요구 사항 | PHP, 운영체제, SQL Server 버전을 지원합니다. |
| 지원 매트릭스 | PHP 드라이버 릴리스에 대한 상세한 호환성 매트릭스입니다. |
| Microsoft PHP for SQL Server 드라이버를 다운로드하세요 | 링크 다운로드 및 아티팩트 공개. |
| 리눅스와 macOS용 설치 튜토리얼 | 드라이버와 ODBC 전제 조건을 Linux와 macOS에 설치하세요. |
| 드라이버 로딩 중 |
php.ini에서 확장을 활성화하세요. |
| 퀵스타트: PHP용 Microsoft 드라이버와 연결하고 쿼리하세요 | 확장 기능을 검증하고, 연결을 설정한 뒤, 동일한 매개변수화된 쿼리를 SQLSRV나 PDO_SQLSRV로 실행하세요. |
| PHP SQL 드라이버 개요 | 패키지에 무엇이 들어 있는지, 그리고 언제 SQLSRV를 선택해야 할지, PDO_SQLSRV 중 하나를 선택해야 하는지. |
구성 및 연결
| 조항 | 설명 |
|---|---|
| 서버에 접속하기 | PHP에서 SQL Server 인스턴스에 연결을 열어보세요. |
| 연결 옵션 | 연결 키워드, 기본값 설정 방법에 대한 완전한 참고 자료입니다. |
| Microsoft Azure SQL Database에 연결 | PHP 애플리케이션을 Azure SQL Database에 연결하세요. |
| 지정된 포트에서 연결 | 비기본 TCP 포트를 타겟팅하세요. |
| 연결 풀링 | PHP 요청 간에 ODBC 연결을 재사용하세요. |
| 다중 활성 결과 세트(MARS) 비활성화 | 호환성을 위해 MARS를 끄세요. |
| LocalDB 지원 | SQL Server LocalDB 인스턴스에 연결하세요. |
| 고가용성 지원, 재해 복구 | 가용성 그룹 리스너 및 다중 서브넷 장애 조치 |
| 유휴 연결 복원력 | 끊어진 유휴 연결에 대한 자동 재연결. |
Authenticate
| 조항 | 설명 |
|---|---|
| Microsoft Entra 인증을 사용하여 연결 | 관리 신원, 서비스 주체, 액세스 토큰 및 암호 흐름. |
| SQL Server 인증을 이용한 연결 | 사용자 이름과 비밀번호를 입력한 SQL 로그인 파일을 사용하세요. |
| Windows 인증로 연결해 | Windows에서는 통합 인증을 사용하고, Linux와 macOS에서는 Kerberos를 사용하세요. |
Secure
| 조항 | 설명 |
|---|---|
| 보안 고려 사항 | PHP 애플리케이션을 위한 위협 모델 및 심층 방어 가이드. |
| 항상 PHP 드라이버로 암호화되어 있습니다 | 중요한 열에 대한 클라이언트 쪽 암호화를 구성합니다. |
| 보안 엔클레이브를 사용하는 Always Encrypted | 안전한 엔클레이브가 있는 암호화된 열에서 풍부한 연산을 가능하게 합니다. |
데이터 검색 및 업데이트
| 조항 | 설명 |
|---|---|
| 프로그래밍 가이드 | 두 장치 드라이버 모두에 맞는 프로그래밍 작업을 찾아보세요. |
| 실행 함수 비교 | 작업 부하에 맞는 실행 함수를 선택하세요. |
| 직접 및 준비된 문 실행 (PDO_SQLSRV) | 직접 실행과 준비된 진술을 사용할 때. |
| 데이터 검색 | 행, 열, 스트리밍 값을 불러와요. |
| 데이터 업데이트 | 행을 삽입, 업데이트, 삭제합니다. |
| 매개변수화된 쿼리 수행 | SQL 주입으로부터 보호하기 위해 매개변수를 결합하세요. |
| 데이터를 스트림으로 전송하기 | 큰 바이너리 및 문자 값을 SQL Server로 스트리밍하세요. |
| 트랜잭션 수행 | 여러 문장을 함께 커밋하거나 롤백하세요. |
| 테이블 값 매개변수 사용 | 매개변수를 TABLE 저장 프로시저에 전달합니다. |
| 커서 유형을 지정하고 행을 선택하세요 | 전방 전용, 정적, 동적 또는 키셋 커서를 선택하세요. |
데이터 형식
| 조항 | 설명 |
|---|---|
| 데이터 타입 변환 | 드라이버가 PHP 타입을 SQL Server 타입에 매핑하는 방법. |
| 기본 SQL Server 데이터 타입 | 각 PHP 값에 대한 기본 SQL Server 유형. |
| 기본 PHP 데이터 타입 | 각 SQL Server 열 유형별 기본 PHP 유형. |
| SQL Server 데이터 타입 지정(SQLSRV) | 매개변수를 바인딩할 때 SQL Server 타입을 덮어쓰세요. |
| PHP 데이터 타입을 지정하세요 | 가져올 때 PHP 타입을 무시하세요. |
| UTF-8 데이터 송수신 및 가져오기 | SQLSRV의 CharacterSet 옵션이나 PDO_SQLSRV의 PDO::SQLSRV_ATTR_ENCODING 속성을 설정하세요. |
| 리눅스와 macOS에서 ASCII 데이터를 송수신하기 | 비Windows 호스트에서 ASCII 왕복 처리를 하세요. |
| 소수점 및 통화 서식 지정(SQLSRV) | SQLSRV 드라이버로 소수점 과 머니 열을 포맷하세요. |
| 소수 및 통화 서식 지정(PDO_SQLSRV) | PDO_SQLSRV 드라이버로 decimal 및 money 열의 서식을 지정하세요. |
| 비시스템 로컬 설정 | 국소화된 소수점 구분자 및 기타 지역별 고려사항. |
오류 및 진단
| 조항 | 설명 |
|---|---|
| 오류 및 경고 처리 | 두 드라이버 모두에서의 오류 및 경고 처리 |
| 오류 및 경고 처리 구성 (SQLSRV) | SQLSRV 드라이버가 오류와 경고를 어떻게 보고하는지 조정하세요. |
| 오류 및 경고 처리 (SQLSRV) | SQLSRV 함수에서 반환되는 오류를 검사합니다. |
| 로그 활동 | 진단 캡처를 위해 드라이버 로깅을 활성화하세요. |
배포 및 운영
| 조항 | 설명 |
|---|---|
| 성능 튜닝 | 연결 관리, 배치, 준비된 문장, 커서, 메모리, 서버 측 모니터링 등이 포함됩니다. |
| Troubleshooting | 일반적인 설치, 연결, 쿼리, 데이터 타입, 트랜잭션, 컨테이너 문제를 진단합니다. |
참조 콘텐츠
| 조항 | 설명 |
|---|---|
| SQLSRV 드라이버 API 참조 | 모든 sqlsrv_* 함수, 매개변수, 반환값. |
| PDO_SQLSRV 드라이버 참조 | PDO_SQLSRV 드라이버에서 지원하는 PDO와 PDOStatement 메서드. |
| 상수 | 드라이버가 노출하는 상수, 타입 상수와 인코딩 상수를 포함합니다. |
관련 작업
| 조항 | 설명 |
|---|---|
| 릴리스 노트 | 새로운 기능, 버그 수정, 플랫폼 지원 변경 사항, 다운로드 링크가 포함된 버전별 기록. |
| 문서에 있는 코드 샘플에 대하여 | 이 섹션에서 샘플된 코드에서 사용되는 관례들입니다. |
| PHP SQL 드라이버용 코드 샘플 | SQLSRV 및 PDO_SQLSRV를 위한 전체 과정 예제 애플리케이션 |
| 지원 리소스 | 커뮤니티와 지원 채널. |
기능 요청
기능을 요청하려면 저장소의 Microsoft Drivers for PHP SQL Server GitHub 이슈를 열어보세요.