Несовместимый тип объекта при создании и изменении функции табличного значения в SQL

Я получаю ошибку ниже для данной функции.

Сообщение 2010, Уровень 16, Состояние 1, Процедура GetTableFromDelimitedValues, Строка 2 Невозможно выполнить изменение для dbo.GetTableFromDelimitedValues, так как это несовместимый тип объекта.

IF NOT EXISTS(SELECT 1 FROM sys.objects 
              WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]'))
BEGIN
   EXECUTE('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues](@input varchar(max),
       @delimiter char(1) = ",")) RETURNS @Result TABLE (
       Value nvarchar(4000)) AS BEGIN RETURN END')
END
GO


ALTER FUNCTION [dbo].[GetTableFromDelimitedValues](
       @input varchar(max),
       @delimiter char(1) = ',')
RETURNS @Result TABLE
(
       Value nvarchar(4000)
)
AS
BEGIN
    DECLARE @position int;
    DECLARE @column nvarchar(4000);

    WHILE LEN(@input) > 0
    BEGIN
        SET @position = CHARINDEX(@delimiter, @input);
        IF (@position < 0) OR (@position IS NULL)
        BEGIN
            SET @position = 0;
        END

        IF @position > 0 
        BEGIN
            SET @column = SUBSTRING(@input, 1, @position - 1);
            SET @input = SUBSTRING(@input, @position + 1, LEN(@input) - @position)
        END
        ELSE
        BEGIN
            SET @column = @input;
            SET @input = '';
        END 

        INSERT @Result (Value) 
        SELECT @column;
    END;

    RETURN;                
END
GO

Может кто-нибудь, пожалуйста, помогите мне получить совместимый тип, исправив функцию?

6 ответов

Вам нужно СОЗДАТЬ и СОЗДАТЬ функцию в этом конкретном контексте

Поскольку в возвращаемом типе функции есть изменения, мы должны удалить, а затем воссоздать функцию.

Есть три типа функций,

  • скаляр
  • Встроенная таблица оценена и
  • Мульти заявление

ALTER нельзя использовать для изменения типа функции.

IF  EXISTS (SELECT [name] FROM sys.objects 
            WHERE object_id = OBJECT_ID('GetTableFromDelimitedValues'))
BEGIN
   DROP FUNCTION [GetTableFromDelimitedValues];
END
GO

/*  Now create function */
CREATE FUNCTION [dbo].[GetTableFromDelimitedValues](
       @input varchar(max),
       @delimiter char(1) = ',')
RETURNS @Result TABLE (
       Value nvarchar(4000)
)
AS
BEGIN
..
..
..
RETURN;
END

в OBJECT_ID функции вам нужно передать только имя функции, а не схему. и зачем создавать его 1-й, а затем Alter Это. Просто проверьте существование 1-го, если оно существует, затем удалите функцию и создайте свою функцию, как я показал выше.

Также не добавляйте Type в предложении where при проверке существования, если есть другой объект, не функция, а какой-либо другой объект с тем же именем, он не подхватит его в вашем операторе select, и вы в конечном итоге создадите функцию с именем, в котором объект уже существует (это выдаст ошибку).

Если вы хотите сделать это по-своему, вот как вы бы это сделали

IF NOT EXISTS(SELECT 1 FROM sys.objects 
              WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]'))
BEGIN
   EXECUTE('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues]() RETURNS @Result TABLE (
       Value nvarchar(4000)) AS BEGIN RETURN END')
END
GO

В моем случае это произошло, когда у меня имя таблицы совпадает с именем процедуры. поэтому изменение имени процедуры или таблицы, указанной в процедуре, также должно исправить это сообщение об ошибке.

У меня есть что сообщить о вашей ошибке, связанной с вашим кодом:
Ошибка говорит Cannot perform alter on 'dbo.GetTableFromDelimitedValues' because it is an incompatible object type
Это означает, что вы должны смотреть на свои строки после ALTER....
И да, есть:
@input varchar(max)
SQL Server 2008 R2 не принимает объекты varchar(MAX), но это только если вы запустите хранимую процедуру
Потому что если вы создаете таблицу вручную, то она полностью ее принимает.
Если вы хотите большую ячейку, введите varchar(1024) или же varchar(2048) оба они приняты. Я столкнулся с этой проблемой несколько дней назад...
Это мое скромное мнение

ДОПОЛНИТЕЛЬНЫЕ ИЗМЕНЕНИЯ
Использовать этот

IF NOT EXISTS(SELECT 1 FROM sys.objects 
WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]')) 
BEGIN 
execute('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues]( @input varchar(max), @delimiter char(1)= ",") RETURNS @Result TABLE ( Value nvarchar(4000)) AS BEGIN RETURN END')
END GO


.... Обратите внимание на изменение с "на"

** ДОПОЛНИТЕЛЬНЫЕ ИЗМЕНЕНИЯ **

Я использую следующее, которое также работает нормально... без каких-либо проблем...

IF  EXISTS (SELECT [name] FROM sys.objects 
            WHERE object_id = OBJECT_ID('GetTableFromDelimitedValues'))
BEGIN
   DROP FUNCTION [GetTableFromDelimitedValues];
END
BEGIN
   execute('CREATE FUNCTION [dbo].[GetTableFromDelimitedValues]() 
    RETURNS 
    @Result TABLE (
    Value nvarchar(4000)) 
    AS 
    BEGIN 
    RETURN 
    END')
    execute('ALTER FUNCTION [dbo].[GetTableFromDelimitedValues](
       @input varchar(max),
       @delimiter char(1) = ",")
       RETURNS @Result TABLE (
       Value nvarchar(4000))
       AS 
    BEGIN 
    RETURN 
    END')
END
GO

Я подтверждаю, что приведенный ниже код работает. Кажется, проблема была в том, что во время моей разработки была создана функция скалярного значения с тем же именем, и в ней произошла ошибка, так как функция выражения alter для таблицы значений из нескольких частей скрипта совместима с ней.

IF NOT EXISTS(SELECT 1 FROM sys.objects 
              WHERE object_id = OBJECT_ID('[GetTableFromDelimitedValues]'))
BEGIN
   EXEC sp_executesql 
    @statement = N'CREATE FUNCTION dbo.[GetTableFromDelimitedValues] () RETURNS @Result 
    TABLE(Value nvarchar(4000))
    AS 
    BEGIN 
      RETURN 
    END' ;
END
GO

ALTER FUNCTION [dbo].[GetTableFromDelimitedValues](
    @input varchar(max),
    @delimiter char(1) = ',')
RETURNS @Result TABLE
(
    Value nvarchar(4000)
)
AS
BEGIN
    DECLARE @position int;
    DECLARE @column nvarchar(4000);

    WHILE LEN(@input) > 0
    BEGIN
        SET @position = CHARINDEX(@delimiter, @input);
        IF (@position < 0) OR (@position IS NULL)
        BEGIN
            SET @position = 0;
        END

        IF @position > 0 
        BEGIN
            SET @column = SUBSTRING(@input, 1, @position - 1);
            SET @input = SUBSTRING(@input, @position + 1, LEN(@input) - @position)
        END
        ELSE
        BEGIN
            SET @column = @input;
            SET @input = '';
        END 

        INSERT @Result (Value) 
        SELECT @column;
    END;

    RETURN;                
END
GO

введите описание изображения здесь

  • ошибка в том, что функция создана, а возврат данных не определяется полем, просто измените его после возврата из таблицы (добавить поле).
  • ошибка исправления решения:
  • удаленная функция просто
  • редактировать ключевую работу "Alter" => "Create"
  • F5 - функция создания - успех
Другие вопросы по тегам