【问题标题】:Stored procedure not returning results from table variable?存储过程不从表变量返回结果?
【发布时间】:2017-05-12 21:59:01
【问题描述】:

我有一个正在处理的存储过程,我试图让它返回存储到我在该过程中创建的表变量中的结果。出于某种原因,当我执行该过程时它没有返回任何内容。但是,如果我将用于填充表变量的代码从程序中取出,它就可以工作......

代码如下:

测试代码

DECLARE @RC int
DECLARE @constraint_names nvarchar(max)
DECLARE @column_names nvarchar(max)
DECLARE @table_name nvarchar(max)
DECLARE @table_schema nvarchar(max)
DECLARE @database_name nvarchar(max)
DECLARE @debug int
DECLARE @ExistFlag int;

-- TODO: Set parameter values here.
SET @column_names = 'M2016_Object_ID int, Name varchar(50), a int, b'
SET @table_name = 'tblM2016_Objects';
SET @debug = 0;
SET @ExistFlag = 1;

DECLARE @existing_cols TABLE (Value nvarchar(max));
INSERT INTO @existing_cols EXEC spM2016_CheckColumnExistence_tblM2016 
@column_names, @table_name,  @database_name, @table_schema, 1, 0;
select * from @existing_cols

结果

Value
M2016_Object_ID int
Name varchar(50)

这是预期的结果,因为我正在测试 tblM2016_Objects 表中是否存在 M2016_Object_ID 和 Name 列。

但是,当我在正在处理的存储过程中执行此操作时,它什么也不返回。

存储过程

ALTER PROCEDURE spM2016_ChangePKConstraints_tblM2016 
-- Add the parameters for the stored procedure here
    @constraint_names   nvarchar(max) = 
N'PK_tblM2016_Fields_M2016_Field_ID',
    @column_names       nvarchar(max) = N'M2016_Field_ID',
    @table_name         nvarchar(max) = N'tblM2016_Fields', 
    @table_schema       nvarchar(max) = N'dbo',
    @database_name      nvarchar(max) = N'MET',
    @debug              int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here
DECLARE @tbl_name       nvarchar(max) = N'tblM2016_Fields',
        @col_names      nvarchar(max) = N'M2016_Field_ID',
        @tbl_schema     nvarchar(max) = N'dbo',
        @db_name        nvarchar(max) = N'MET',
        @tbl_full_name  nvarchar(max),
        @tbl_short_name nvarchar(max),
        @sql            nvarchar(max),
        @params         nvarchar(max)

-- Insert statements for procedure here

SET @col_names = ISNULL(NULLIF(@column_names, ''), @col_names);
SET @tbl_name = quotename(ISNULL(NULLIF(@table_name, ''), @tbl_name));
SET @tbl_schema = quotename(ISNULL(NULLIF(@table_schema, ''), @tbl_schema));
SET @db_name = quotename(ISNULL(NULLIF(@database_name, ''), @db_name));

SET @tbl_full_name =  @db_name + '.' + @tbl_schema + '.' + @tbl_name;
SET @tbl_short_name = @tbl_schema + '.' + @tbl_name;

DECLARE @existing_cols TABLE (Value nvarchar(max));
DECLARE @nonexisting_cols TABLE (Value nvarchar(max));

--INSERT INTO @split_columns
--  SELECT *
--  FROM 
--  fnM2016_Split_String_Inline(@col_names, ',');

--IF (@debug = 1)
--  SELECT * FROM @split_columns;

IF NOT EXISTS (SELECT * FROM sys.objects WHERE type = 'PK' AND parent_object_id = OBJECT_ID(@tbl_full_name))
BEGIN
    -- No PK constraint, check col_names to see which exist and don't exist
    INSERT INTO @existing_cols EXEC spM2016_CheckColumnExistence_tblM2016 @col_names, @tbl_name,  @db_name, @tbl_schema, 1, 0;

    INSERT INTO @nonexisting_cols EXEC spM2016_CheckColumnExistence_tblM2016 @col_names, @tbl_name,  @db_name, @tbl_schema, 0, 0;

    SELECT * FROM @existing_cols;

    SELECT * FROM @nonexisting_cols;

END
--ELSE
--BEGIN

--END

END

结果 这些是在上面的测试中使用相同的参数值执行过程后的结果:

EXECUTE @RC = [dbo].[spM2016_ChangePKConstraints_tblM2016] 
 @constraint_names
,@column_names
,@table_name
,@table_schema
,@database_name
,@debug;

结果

Value

该表故意没有主键。证明:

【问题讨论】:

  • 在你的过程中,你的表名是@table_name nvarchar(max) = N'tblM2016_Fields',但它应该是tblM2016_Objects
  • 你能显示你传递给spM2016_ChangePKConstraints_tblM2016过程的实际值吗?
  • 测试代码块中使用的参数与传递给spM2016_ChangePKConstraints_tblM2016的参数相同。
  • -- TODO: Set parameter values here. SET @column_names = 'M2016_Object_ID int, Name varchar(50), a int, b' SET @table_name = 'tblM2016_Objects'; SET @debug = 0; SET @ExistFlag = 1;
  • spM2016_CheckColumnExistence_tblM2016中的参数顺序是什么

标签: sql-server stored-procedures sql-server-2016 table-variable


【解决方案1】:

在您的过程中,在您的声明部分更改表的名称。

这应该可以解决问题。

ALTER PROCEDURE spM2016_ChangePKConstraints_tblM2016 
-- Add the parameters for the stored procedure here
    @constraint_names   nvarchar(max) = 
N'PK_tblM2016_Fields_M2016_Field_ID',
    @column_names       nvarchar(max) = N'M2016_Field_ID',
    @table_name         nvarchar(max) = N'tblM2016_Objects', 
    @table_schema       nvarchar(max) = N'dbo',
    @database_name      nvarchar(max) = N'MET',
    @debug              int = 0
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

-- Insert statements for procedure here
DECLARE @tbl_name       nvarchar(max) = N'tblM2016_Objects',
        @col_names      nvarchar(max) = N'M2016_Field_ID',
        @tbl_schema     nvarchar(max) = N'dbo',
        @db_name        nvarchar(max) = N'MET',
        @tbl_full_name  nvarchar(max),
        @tbl_short_name nvarchar(max),
        @sql            nvarchar(max),
        @params         nvarchar(max)

【讨论】:

  • 我认为这不会起作用,因为我的 spM2016_CheckColumnExistence 具有相同的默认参数,并且当我在测试代码中直接调用它时不会导致它失败。这些值主要用于 null 比较,以防表名参数以 null 或空字符串形式传递。
【解决方案2】:

我发现了这个问题。我的@table_name@table_schema@database_name 被传递到spM2016_ChangePKConstraints_tblM2016 内的spM2016_CheckColumnExistence_tblM2016 过程中,已经通过对quotename() 的调用进行了转义。在spM2016_CheckColumnExistence_tblM2016 中,我还对参数进行qutoename(),作为对坏表、数据库和模式名称的验证检查。该程序代码被遗漏了,对此我深表歉意。

基本上问题区域在这里(问题参数用**突出显示)

spM2016_ChangePKConstraints_tblM2016中的问题代码

INSERT INTO @existing_cols EXEC spM2016_CheckColumnExistence_tblM2016 @col_names, **@tbl_name**,  **@db_name**, **@tbl_schema**, 1, 0;

请注意,传递给spM2016_CheckColumnExistence_tblM2016 的那些参数已经在spM2016_ChangePKConstraints_tblM2016 过程中使用上面的quotename() 进行了转义。现在,这是spM2016_CheckColumnExistence_tblM2016 过程中缺少的关键代码:

spM2016_CheckColumnExistence_tblM2016 中的问题代码

ALTER PROCEDURE spM2016_CheckColumnExistence_tblM2016 
-- Add the parameters for the stored procedure here
@column_names   nvarchar(max) = N'M2016_Field_ID int', 
@table_name     nvarchar(max) = N'tblM2016_Fields',
@database_name  nvarchar(max) = N'MET',
@table_schema   nvarchar(max) = N'dbo',
@ExistFlag      int          = 1,                       -- Check for column existence in given table = 1
                                                        -- Check for column non-existence in given table = 0
@debug          int          = 0                    
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;

 -- Insert statements for procedure here
DECLARE @tbl_name       nvarchar(max) = N'tblM2016_Fields',
        @col_names      nvarchar(max) = N'M2016_Field_ID',
        @tbl_schema     nvarchar(max) = N'dbo',
        @db_name        nvarchar(max) = N'MET',
        @tbl_full_name  nvarchar(max),
        @tbl_short_name nvarchar(max)

-- Insert statements for procedure here

***** PROBLEM STARTS HERE *****
SET @col_names = ISNULL(NULLIF(@column_names, ''), @col_names);
SET @tbl_name = quotename(ISNULL(NULLIF(@table_name, ''), @tbl_name));
SET @tbl_schema = quotename(ISNULL(NULLIF(@table_schema, ''), @tbl_schema));
SET @db_name = quotename(ISNULL(NULLIF(@database_name, ''), @db_name));

SET @tbl_full_name =  @db_name + '.' + @tbl_schema + '.' + @tbl_name;
SET @tbl_short_name = @tbl_schema + '.' + @tbl_name;

为了清楚起见,我已经用 ***** 问题从这里开始 ***** 突出显示了这个问题。如您所见,spM2016_CheckColumnExistence_tblM2016 还进行了 quotename 调用,以确保传递给 spM2016_CheckColumnExistence_tblM2016@table_name@table_schema@database_name 也具有正确的转义。但是,由于我将已经引用的 @table_name@table_schema@database_namespM2016_ChangePKConstraints_tblM2016 传递到 spM2016_CheckColumnExistence_tblM2016 作为 @col_names, @tbl_name, @db_name, @tbl_schema,它们被双引号引起来,因此在 sys.object 查询中进行比较时无法识别在spM2016_CheckColumnExistence_tblM2016 等返回虚假结果。

测试代码起作用的原因是因为参数在传递到spM2016_CheckColumnExistence_tblM2016时尚未转义,从而导致表变量执行正常。

原来,它与表变量无关:/

【讨论】:

    猜你喜欢
    • 2013-06-21
    • 2021-03-22
    • 1970-01-01
    • 2017-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多