【问题标题】:Create USER in SQL Server generates error: SUBQUERY RETURNED MORE THAN 1 VALUE在 SQL Server 中创建 USER 生成错误:SUBQUERY RETURNED MORE THAN 1 VALUE
【发布时间】:2017-05-31 22:44:54
【问题描述】:

我有一个 Delphi XE3 应用程序,它在 SQL Server 数据库中创建用户和登录名。我使用了 FireDAC TAdConnectionTADQuery 和两个 TAdScript 来执行 SQL 语句来创建用户和登录名。当我尝试在 SQL Server 上创建登录时,用于创建登录的 SQL 语句工作正常

CREATE LOGIN LOGIN_NAME 
WITH PASSWORD='PASSWORD', CHECK_POLICY = OFF, 
DEFAULT_DATABASE = DATABASE

但是当我尝试通过数据库创建用户时

CREATE USER USER_NAME 
FOR LOGIN LOGIN_NAME WITH DEFAULT_SCHEMA=dbo

代码返回错误:

子查询返回超过 1 个值。当子查询跟随 =,!=,,>= 或子查询用作表达式时,这是不允许的

我尝试使用TAdConnectionTAdQueryTADScript 执行SQL 语句,但它们都返回相同的错误。

你能帮忙吗?

更新 1:感谢您的帮助和 cmets

这是我使用 SQL Server Management Studio 创建数据库用户时的结果

CREATE USER KDESAR12 FOR LOGIN KDESAR12 
WITH DEFAULT_SCHEMA=dbo

结果

(受影响的 1 行)

用于获取数据库触发器的查询

select * from KACTUSDESARROLLO.sys.triggers where parent_class_desc = 'DATABASE'

返回 0 行

我的Delphi代码如下:

//Using TADScript
  try
    lStSQL := 'SET CMDSEP ;';
    lStSQL := lStSQL + ' USE MY_DATABASE_NAME; ';

    lStSQL := lStSQL + ' CREATE USER KDESAR12 FOR LOGIN KDESAR12 WITH DEFAULT_SCHEMA=dbo;';

    ADScript1.SQLScripts.Add.SQL.Text := lStSQL;
    ADScript1.ValidateAll;
    ADScript1.ExecuteAll;

  except on E: exception do
    begin
      ShowMessage(E.Message);
    end;
  end;

//Using TADQuery
  try
    lStSQL := ' CREATE USER KDESAR12 FOR LOGIN KDESAR12 WITH DEFAULT_SCHEMA=dbo;';

    ADQuery2.SQL.Add (lStSQL);
    ADQuery2.ExecSQL;

  except on E: exception do
    begin
      ShowMessage(E.Message);
    end;
  end;

//Using TADConnection
  try
    lStSQL := ' CREATE USER KDESAR12 FOR LOGIN KDESAR12 WITH DEFAULT_SCHEMA=dbo;';

    ADConnection1.ExecSQL (lStSQL);

  except on E: exception do
    begin
      ShowMessage(E.Message);
    end;
  end;

所有组件都返回相同的错误

【问题讨论】:

  • 您是否在 SQL Server Management Studio 上尝试过该指令?您将能够缩小可能性,确定问题出在 ADO 组件中,还是您的数据库本身。
  • "select * from sys.triggers where parent_class_desc = 'MY_DATABASE_NAME'" 不正确。应该是“select * from MY_DATABASE_NAME.sys.triggers where parent_class_desc = 'DATABASE'”
  • 感谢 @DavidBrowne-Microsoft 它也返回 0 行 select * from KACTUSDESARROLLO.sys.triggers where parent_class_desc = 'DATABASE'

标签: sql-server delphi firedac


【解决方案1】:

该语句可能导致该错误的唯一方法是 DDL 触发器。 EG

CREATE TRIGGER create_user_trigger 
ON DATABASE 
FOR create_user
AS 
   declare @id int = (select object_id from sys.objects);
;
go

【讨论】:

  • Erik,如果您从管理工作室运行这些命令,也会发生同样的情况吗?如果没有,你能提供你的 Delphi 代码吗?
  • 请执行代码:select * from sys.triggers where parent_class_desc = 'DATABASE'
  • @Victoria Delphi 代码使用 TADQuery try lStSQL := ' CREATE USER KDESAR12 FOR LOGIN KDESAR12 WITH DEFAULT_SCHEMA=dbo;'; ADQuery2.SQL.Add (lStSQL); ADQuery2.ExecSQL; except on E: exception do begin ShowMessage(E.Message); end; end;
  • @Victoria Delphi 代码使用 TAdConnection try lStSQL := ' CREATE USER KDESAR12 FOR LOGIN KDESAR12 WITH DEFAULT_SCHEMA=dbo;'; ADConnection1.ExecSQL (lStSQL); except on E: exception do begin ShowMessage(E.Message); end; end;
  • 您可以对 Delphi 发送的任何其他命令使用 SQL Profiler 或扩展事件。
【解决方案2】:

感谢大家的帮助。我结束了针对另一台服务器中的另一个数据库的代码测试,它创建了登录就好了。 因此,我向 DBA 询问了这些环境之间的差异,他向我指出了他用于审计目的的服务器触发器。一旦他在第一台服务器上禁用它,代码就会按预期工作。

对于后代,除了像@David Browne - Microsoft 所说的那样检查数据库触发器之外,还可以像这样检查服务器触发器:

SELECT * FROM sys.server_triggers

再次感谢

【讨论】:

    猜你喜欢
    • 2016-03-03
    • 1970-01-01
    • 2018-06-28
    • 1970-01-01
    • 1970-01-01
    • 2019-10-18
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多