#php #sql #sql-server #tsql #pdo
#php #sql #sql-сервер #tsql #pdo
Вопрос:
Я пишу код для создания базы данных MSSQL с нуля, используя PHP PDO. Я создал базу данных, и теперь мне нужно выполнить кучу инструкций, загруженных из файла .SQL, Для создания таблиц, данных и т. Д. Первые несколько строк
EXEC sp_dbcmptlevel 'myDbName', 120
GO
IF (1 = FULLTEXTSERVICEPROPERTY('IsFullTextInstalled'))
BEGIN
EXEC [myDbName].[dbo].[sp_fulltext_database] @action = 'enable'
END
GO
ALTER DATABASE [myDbName] SET ANSI_NULL_DEFAULT OFF
GO
EXEC sp_dbcmptlevel 'myDbName', 120
...
Если я запускаю .SQL-файл непосредственно в SSMS, он работает отлично. Если я загружу его и выполню через PHP PDO, я получу
Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: [Microsoft][ODBC Driver 11 for SQL Server][SQL Server]Incorrect syntax near 'GO'.' in ...
Глядя на профилировщик, мой запрос предваряется / оборачивается
declare @p1 int
set @p1=NULL
exec sp_prepexec @p1 output,NULL,N'EXEC sp_dbcmptlevel ''myDbName', 120
...
и похоже, что с подготовленной оболочкой выполнения серверу это не нравится. Я выполняю скрипт, который я загружаю из файла SQL с помощью
$db = new PDO('sqlsrv:Server='.$serverName.';Database='.$databaseName, $username, $password);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::SQLSRV_ATTR_ENCODING, PDO::SQLSRV_ENCODING_UTF8);
$db->prepare($mySqlScript)->execute();
Как я могу исправить синтаксическую ошибку, чтобы выполнить весь набор команд, загружаемых PHP из файла SQL?
Ответ №1:
Вы должны были разделить свой скрипт с помощью предложения «GO» на несколько инструкций, а затем запускать их один за другим.
Что-то вроде:
$script = file_get_contents('script.sql');
$statements = explode( 'GO', $script );
foreach( $statements as $statement ) {
// here execute the $statement
$sth = $dbh->prepare($statement);
$sth->execute();
}
Это то, что SSMS делает внутренне, разбивает инструкции на «GO» перед их выполнением.
Комментарии:
1. Отлично, спасибо. Это приходило мне в голову как хак, но не как требуемый способ. Знаете ли вы, в чем причина невозможности выгрузить весь скрипт? Я бы подумал, что из-за проблем с производительностью было бы лучше иметь возможность обрабатывать все за один раз.
2. Вероятно, это не было одной из целей библиотеки, и это поведение достаточно легко реализовать, поэтому нам пришлось с ним справиться. Вы можете закодировать его как
function execScript( $scriptPath ) { // Do the split and the execution }
и в своем коде обрабатывать его так, как если бы он был частью исходной библиотеки. Это то, что библиотека будет делать (более или менее) любым способом.