이 가이드를 사용해 연결을 열고 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 유형을 교환 가능하게 만들지는 않습니다.
연결 전에
- 지원되는 PHP 런타임과 Microsoft ODBC 드라이버를 설치하고, 사용할 PHP 확장 프로그램을 불러오세요.
- 애플리케이션을 실행하는 PHP 프로세스를 확인하세요.
php --ini을 실행하면 명령줄 구성을 찾을 수 있고php -m을 실행하면 로드된 확장 기능을 나열할 수 있습니다. SQLSRV는sqlsrv이(가) 필요합니다. PDO_SQLSRV는PDO와pdo_sqlsrv를 필요로 한다. 웹 서버는 터미널과는 다른php.ini, 런타임 및 계정을 사용할 수 있습니다. - 서버 주소, 데이터베이스 이름, 그리고 연결 권한이 있는 계정을 얻으세요. 데이터베이스 로그인이 모든 테이블에 자동으로 권한을 부여하는 것은 아닙니다.
- 네트워크 접근과 신뢰할 수 있는 서버 인증서를 설정하세요. 이 프로그램들은 암호화와 인증서 검증을 명시적으로 요청합니다. 인증서에 명시된 호스트 이름으로 연결하고, 인증서에 포함되지 않은 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() 페이지를 노출하지 마세요. |
| 이후 작업은 닫힌 핸들에서 실패합니다 | 모든 문 작업 내내 연결을 유지하세요. 연결을 닫은 후 새 연결을 생성하세요; 오래된 핸들은 스스로 열리지 않습니다. |
기타 관련 문서
- 지정된 포트에서 연결
- 연결 옵션
- 연결 풀링
- 다중 활성 결과 세트(MARS) 비활성화
- LocalDB 지원
- 고가용성 및 재해 복구 지원
- Microsoft Azure SQL Database에 연결
- 유휴 연결 복원력