0

У меня есть хранимая процедура, над которой я работаю, и я пытаюсь вернуть ее, чтобы вернуть результаты, которые хранятся в переменной таблицы, которую я создал в ходе процедуры. По какой-то причине он ничего не возвращает, когда я выполняю процедуру. Однако, если я беру кусок кода, используемого для заполнения таблицы переменной и вывести его из процедуры он работает ...Сохраненная процедура не возвращает результаты из переменной таблицы?

Код выглядит следующим образом:

Код проверки

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) 

Это ожидаемый результат, так как я тестирование чтобы увидеть, существуют ли столбцы M2016_Object_ID и Name в таблице tblM2016_Objects.

Однако, когда я выполняю это внутри хранимой процедуры, над которой я работаю, она ничего не возвращает.

хранимой процедуры

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 

В таблице специально нет первичного ключа. Доказательство. enter image description here

+0

В вашей процедуре, у вас есть имя таблицы, как '@TABLE_NAME NVARCHAR (макс) = N'tblM2016_Fields'', но оно должно быть' tblM2016_Objects' –

+0

Можете ли вы показать фактические значения, которые вы передаете в процедуру 'spM2016_ChangePKConstraints_tblM2016'? –

+0

Параметры, используемые в блоке тестового кода, те же, что и для spM2016_ChangePKConstraints_tblM2016. – Jake

ответ

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) 
+0

Я не думаю, что это сработало бы, потому что мой spM2016_CheckColumnExistence имеет одинаковые параметры по умолчанию, и это не приводит к сбою, когда я вызываю его прямо в тестовый код. Эти значения в основном используются для нулевых сравнений в случае, если параметр имени таблицы передается в пустой или пустой строке. – Jake

0

Я понял вопрос. Мои @table_name, @table_schema и @database_name, переданные в процедуру spM2016_CheckColumnExistence_tblM2016 внутри spM2016_ChangePKConstraints_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 уже отделались quotename() выше в процедуре spM2016_ChangePKConstraints_tblM2016.Теперь, вот недостающий код ключа в 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 также звонит по коду, чтобы убедиться, что @table_name, @table_schema и @database_name, переданные в spM2016_CheckColumnExistence_tblM2016, имеют надлежащее экранирование. Но, так как я прошел уже quotenamed @table_name, @table_schema и @database_name из spM2016_ChangePKConstraints_tblM2016 в spM2016_CheckColumnExistence_tblM2016 как @col_names, @tbl_name, @db_name, @tbl_schema, они получили двойные кавычки и, таким образом, неузнаваемыми при выполнении сравнений в sys.object запросов в spM2016_CheckColumnExistence_tblM2016 и поэтому возвращались фиктивные результаты.

Причина, по которой тестовый код работал, заключается в том, что параметры не были экранированы при передаче в spM2016_CheckColumnExistence_tblM2016, что привело к тому, что переменная таблицы выполнялась нормально.

Оказывается, это не имеет ничего общего с переменной таблицы:/