【问题标题】:Create Trigger from Delphi Code using Native Client Driver使用本机客户端驱动程序从 Delphi 代码创建触发器
【发布时间】:2012-09-25 01:14:52
【问题描述】:

我有一个插入触发器,其中包含存储为 XE2 项目资源的动态 sql。它还包含在 Delph 代码运行以执行 SQL 时替换的数据库名称和表名称的占位符。

最初我对 SqlExpress 数据库使用 DevArt SQL Server 驱动程序,但现在我想对 LocalDB 数据库使用 ODBC 和 SQL Native Client 驱动程序。

我发现我原来的创建触发器脚本不再起作用了。

我正在使用 TSQLQuery.ExecSQL 来执行我的 SQL 命令。

CREATE TRIGGER [dbo].[#TableName#_INSERT_TRIGGER] ON [#DatabaseName#].[dbo].[#TableName#] FOR INSERT

导致

'[Microsoft][SQL Server Native Client 11.0][SQL Server]无法在 'EvaluationCompany_COPYDB.dbo.COPY_PRODUCTS' 上创建触发器,因为目标不在当前数据库中。'

我使用的解析器类确实将 GO 关键字处的 SQL 脚本拆分为单独的语句,所以我修改了我的创建触发器脚本说

USE [#DatabaseName#]
GO
CREATE TRIGGER [dbo].[#TableName#_INSERT_TRIGGER] ON [dbo].[#TableName#] FOR INSERT

这就是你在 SSMS 中会做的事情,但那是说

'[Microsoft][SQL Server Native Client 11.0][SQL Server]对象'dbo.COPY_PRODUCTS'不存在或对该操作无效。'

可能是因为 CREATE 的“当前数据库”不是 USE 设置的,因为它似乎被遗忘了。

我尝试了将 sql 语句串成单个执行的常用方法

USE [#DatabaseName#];
CREATE TRIGGER [dbo].[#TableName#_INSERT_TRIGGER] ON [dbo].[#TableName#] FOR INSERT

但这会引发预期的

'[Microsoft][SQL Server Native Client 11.0][SQL Server]'CREATE TRIGGER' 必须是查询批处理中的第一条语句。'

所以我将整个 CREATE...END 包装在 EXEC [#DatabaseName#].[sys].[sp_ExecuteSQL] N' ' 中并尝试执行它。如果我将字符串变量的内容粘贴到 SSMS 中,它可以正常执行,但是当传递给 ExecSQL 时,它会说

'[Microsoft][SQL Server Native Client 11.0][SQL Server]对过程'sp_executesql'的请求失败,因为'sp_executesql'是一个过程对象。'

这有点荒谬。所以现在我不知道如何使用 dbExpress 和 SQL Server 本机客户端在表上创建触发器。

【问题讨论】:

  • 只是一个健全性检查,确保你使用正确的数据库,表存在,并检查表的所有权与你用来访问它的用户是否匹配。

标签: sql sql-server delphi delphi-xe2 dbexpress


【解决方案1】:

我不确定到底是什么问题,但我能够成功运行以下代码。 也许它会给你一个线索。

uses
  Data.Win.AdoDB;

procedure TForm1.Button1Click(Sender: TObject);
var
  aConnection : tAdoConnection;

  procedure InitializeAdoConnection;
  begin
    aConnection := tAdoConnection . Create ( self );

    with aConnection do
      begin
        ConnectionString :=   'Provider=MSDASQL.1;'
                            + 'Password=' + gPassword + ';'
                            + 'Persist Security Info=True;'
                            + 'User ID=' + gUserName + ';'
                            + 'Data Source=' + gOdbcAlias + ';'
                            + 'Extended Properties="DSN=' + gOdbcAlias + ';'
                            + 'UID=' + gUserName + ';'
                            + 'PWD=' + gPassword + ';'
                            + 'APP=Enterprise;'
                            + 'WSID=' + gMachineName + ';'
                            + 'DATABASE=master";'
                            + 'Initial Catalog=master';
        LoginPrompt := false;
        Connected := true;
      end;
  end;

  procedure ExecuteCommand ( const nSqlCommand : string );
  begin
    with tAdoCommand . Create ( nil ) do
      try
        Connection := aConnection;
        CommandText := nSqlCommand;
        Execute;
      finally
        Free;
      end;
  end;

  procedure QueryResults;
  begin
    with tAdoQuery . Create ( nil ) do
      try
        Connection := aConnection;
        SQL . Text := 'select * from COPY_PRODUCTS';
        Open;

        while not EOF do
          begin
            Memo1 . Lines . Add ( 'ID='
                  + inttostr ( FieldByName ( 'PRODUCT_ID' ) . AsInteger )
                  + ' Name='
                  + FieldByName ( 'PRODUCT_NAME' ) . AsString );

            Next;
          end;


      finally
        Free;
      end;
  end;

begin
  InitializeAdoConnection;

//  ExecuteCommand ( 'drop database EvaluationCompany_COPYDB' );

  ExecuteCommand ( 'create database EvaluationCompany_COPYDB' );

  ExecuteCommand ( 'use EvaluationCompany_COPYDB' );

  ExecuteCommand ( 'create table dbo.COPY_PRODUCTS '
                   + '( PRODUCT_ID int identity(1,1),'
                   + '  PRODUCT_NAME varchar(50) )' );

  ExecuteCommand ( 'create trigger dbo.COPY_PRODUCTS_INSERT_TRIGGER '
                   + 'on dbo.COPY_PRODUCTS '
                   + 'for insert '
                   + 'as '
                   + 'begin '
                   + '  update COPY_PRODUCTS '
                   + '    set PRODUCT_NAME = PRODUCT_NAME + ''!'' '
                   + '    where PRODUCT_ID in '
                   + '    ( select PRODUCT_ID from INSERTED )'
                   + 'end ' );

  ExecuteCommand ( 'insert into COPY_PRODUCTS ( product_name ) '
                   + 'values ( ''Stacky Goodness'' ) ' );

  QueryResults;
end;

【讨论】:

  • 使用 TADOConnection 和 TADOCommand 确实有效,而使用 TSQLConnection 和 TSQLQuery 却没有。不幸的是,我最初仅限于使用现有的类来执行我的触发脚本,因此我很挣扎。
猜你喜欢
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-06
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多