Как запустить файл сценария базы данных из Delphi?

#sql-server #delphi #ado

#sql-сервер #delphi #ado

Вопрос:

Я хочу сделать следующее. 1) Создайте базу данных. 2) Запускайте скрипт при создании таблиц, хранимых процедур и т.д. (этот скрипт создается с помощью опции SMS «генерировать скрипты»)

Я нашел следующий код:http://www.delphipages.com/forum/showthread.php?t=181685 и изменил его на этот:

попробуйте

 ADOQuery.ConnectionString := 'Provider=SQLOLEDB.1;Password='  
  

edtPassword.Текст
‘; Сохраняемая информация о безопасности = True; Идентификатор пользователя = ‘ edtUser.Text
‘;Начальный каталог = master; Источник данных =’
Имя_сервера.Текст;

 ADOQuery.SQL.Clear;
ADOQuery.SQL.Text := 'create DataBase '   edtWebDBName.Text;
ADOQuery.ExecSQL; // should check existance of database
ADOWeb.Connected := false;
ADOWeb.ConnectionString := 'Provider=SQLOLEDB.1;Password='  
  

edtPassword.Текст
‘; Сохраняемая информация о безопасности = True; Идентификатор пользователя = ‘ edtUser.Text
‘;Начальный каталог=’ edtWebDBName.Текст ‘;Источник данных =’
Имя_сервера.Текст;
ADOWeb.Подключено:= true;

 ADOQuery.Connection := ADOWeb;
ADOQuery.SQL.Clear;
ADOQuery.SQL.LoadFromFile(edtScriptFileName.Text);
ADOQuery.ExecSQL;   except
  

Это работает до момента запуска файла сценария. Затем он генерирует исключение: неправильный синтаксис рядом с «GO». Если я запускаю скрипт в SMS на вновь созданной базе данных, все в порядке. Связана ли эта проблема с одновременным выполнением более чем одной команды SQL (сценарий, по сути, представляет собой длинный список инструкций command / GO? Как это обойти?

О, также в качестве бонуса, есть какие-нибудь мысли о быстрой проверке, чтобы увидеть, действительно ли новая база данных существует, прежде чем отправлять в нее скрипт? (Или это не обязательно, поскольку при сбое create это сгенерирует исключение?)

Комментарии:

1. Все эти ответы будут работать. Я думаю, что для сценариев, генерируемых SMS, запуск sqlcmd — это правильный путь. Также я использовал приведенное ниже, чтобы получить количество БД. ADOQuery.SQL.Text := ‘ВЫБЕРИТЕ COUNT(*) ИЗ sys.databases, ГДЕ name=’ chr(39) edtWebDBName. Текст chr(39); ADOQuery. Открыть; если ADOQuery. Поля[0]. AsInteger = 0, тогда // DB НЕ СУЩЕСТВУЕТ

Ответ №1:

Оператор Rob GO не распознается ADO, поэтому вы должны удалить его из своего скрипта перед выполнением.

Теперь, чтобы проверить, существует ли база данных, вы можете выполнить запрос, подобный этому

 select COUNT(*) from sys.databases where name='yourdatabasename'
  

проверьте этот очень простой пример

предположим, что у вас есть скрипт, подобный этому

 CREATE TABLE Dummy.[dbo].tblUsers(ID INT, UserName VARCHAR(50))
GO
INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (1, 'Jill')
GO
INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (2, 'John')
GO
INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (3, 'Jack')
GO
  

Теперь, чтобы выполнить это предложение, вы можете сделать что-то вроде этого

 const
//in this case the script is inside of a const string but can be loaded from a file as well
Script=
'CREATE TABLE Dummy.[dbo].tblUsers(ID INT, UserName VARCHAR(50)) ' #13#10 
'GO ' #13#10 
'INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (1, ''Jill'') ' #13#10 
'GO ' #13#10 
'INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (2, ''John'') ' #13#10 
'GO ' #13#10 
'INSERT INTO Dummy.[dbo].tblUsers (ID, UserName) VALUES (3, ''Jack'') ' #13#10 
'GO ';

var
  DatabaseExist : Boolean;
  i             : Integer;
begin
  try
    //check the connection
     if not ADOConnection1.Connected then
      ADOConnection1.Connected:=True;
      //make the query to check if the database called Dummy exist  
      ADOQuery1.SQL.Add(Format('select COUNT(*) from sys.databases where name=%s',[QuotedStr('Dummy')]));
      ADOQuery1.Open;
      try
       //get the returned value, if is greater than 0 then exist 
       DatabaseExist:=ADOQuery1.Fields[0].AsInteger>0;
      finally
       ADOQuery1.Close;
      end;


      if not DatabaseExist then
      begin
       //create the database if not exist
       ADOQuery1.SQL.Text:=Format('Create Database %s',['Dummy']);
       ADOQuery1.ExecSQL;
       ADOQuery1.Close;

       //load the script, remember can be load from a file too  
       ADOQuery1.SQL.Text:=Script;
       //parse the script to remove the GO statements
        for i := ADOQuery1.SQL.Count-1 downto 0 do
          if StartsText('GO',ADOQuery1.SQL[i]) then
           ADOQuery1.SQL.Delete(i);
       //execute the script
       ADOQuery1.ExecSQL;
       ADOQuery1.Close;
      end;
  except
      on E:Exception do
        ShowMessage(E.Message);
  end;

end;
  

Комментарии:

1. Почему -1 здесь? Есть разумная причина для этого?

2. @daemon_x, не волнуйся ;), я так привык к анонимным отказникам, на меня это больше не влияет.

Ответ №2:

Это GO означает завершение пакета только для определенных утилит Microsoft, это неправильный оператор T-SQL. Попробуйте удалять каждое вхождение GO в вашем скрипте, а затем выполнять его. Это GO будет выполнено ADOQuery.ExecSQL для вас в конце вашего скрипта.

И к вашему второму вопросу; вы можете использовать, например, SQL-функцию DB_ID, чтобы проверить, существует ли ваша база данных (вы, конечно, должны быть на том же сервере). Эта функция возвращает идентификатор базы данных; в противном случае NULL, поэтому, если следующая инструкция SQL возвращает NULL, то создание вашей базы данных завершилось неудачей.

 ADOQuery.SQL.Text := 'SELECT DB_ID('   edtWebDBName.Text   ')';
ADOQuery.Open;

if ADO_Query.Fields[0].IsNull then
  ShowMessage('Database creation failed');
  

Ответ №3:

Скрипты могут содержать гораздо больше команд, чем SQL DDL / DML. Они могут содержать переменные, небольшие блоки кода, инструкцию по управлению транзакциями. Обычно существует более одного оператора, разделенных символом завершения (точка с запятой, косая черта Oracle, MSSQL GO и т.д., В зависимости от используемой вами базы данных и синтаксиса ее скрипта). Для правильного выполнения скрипта вы должны проанализировать входной файл, разделить каждую команду и правильно передать ее в базу данных. Вы можете поискать библиотеку для этого (есть несколько, IIRC), или вы можете попробовать использовать инструмент командной строки MS SQL для отправки скрипта через нее.