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

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

Msg 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

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

Ответ 1

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

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

Существует три типа функций,

  • Скалярное
  • Встроенная таблица с оценкой и
  • Multi Statement

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

Ответ 2

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 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

Ответ 3

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

Ответ 4

У меня есть что сообщить о вашей ошибке, связанной с вашим кодом:
Ошибка говорит 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

Ответ 5

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

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