在 SQL 中创建和更改表值函数时对象类型不兼容
Posted
技术标签:
【中文标题】在 SQL 中创建和更改表值函数时对象类型不兼容【英文标题】:Incompatible object type when create and alter a table value function in SQL 【发布时间】:2014-02-20 12:36:33 【问题描述】:我收到给定函数的以下错误。
消息 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】: bug 确实创建了函数,返回的数据不是字段定义的,只是在表(添加字段)返回后更改。 解决方案修复错误: 刚刚删除函数 编辑关键字“Alter” => “Create” F5 创建函数成功【讨论】:
正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center。 请不要将代码包含在图像中。喜欢复制/粘贴【参考方案2】:就我而言,这发生在我的表名与 proc 名称完全相同时。因此更改 proc 名称或 proc 中引用的表也应该修复此错误消息。
【讨论】:
【参考方案3】:你需要DROP和CREATE在这个特定上下文中的函数
由于函数返回类型发生了变化,我们必须删除然后重新创建函数。
函数分为三种,
标量 内联表值和 多语句ALTER 不能用于改变函数类型。
【讨论】:
【参考方案4】: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
函数中,您只需要传递函数名而不是模式。以及为什么要先创建它,然后再创建 Alter
it 。只需检查是否存在 1st 如果它存在然后删除函数并创建你的函数,如我上面所示。
在检查是否存在时也不要在where子句中添加Type
,如果有另一个对象不是函数而是任何其他同名对象,它不会在你的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
【讨论】:
感谢您的回复。最初,我以与您建议的相同的方式解决问题 (Drop|Create),但它没有通过 - DROP 问题,可能有时执行用户可能无权在 prod 环境中进行 DROP,因此开启更安全的一面应该使用 ALTER。 @ary 现在看看我已经更新了我的答案以解决您在实际查询中遇到的问题。 感谢您一直以来的帮助。抱歉,它不起作用并继续显示相同的错误。无法对“dbo.GetTableFromDelimitedValues”执行更改,因为它是不兼容的对象类型。【参考方案5】:我确认以下代码有效。似乎问题是在我的开发过程中以某种方式创建了一个同名的标量值函数,并且由于脚本的多部分表值更改语句函数与其兼容而出现错误。
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
【讨论】:
【参考方案6】:我有一些事情要通知您与代码相关的错误:
错误说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
【讨论】:
感谢您的帮助。抱歉,使用 1024 删除 max 后,它不起作用并继续显示相同的错误。 尝试看看@delimiter char(1) = ',')
语法是否正确......无论如何问题都来自这个领域。
这对我来说很好...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 NOT EXISTS 块中执行 CREATE FUNCTION 工作正常,但我在后面的 ALTER FUNCTION 上遇到问题 - 无法在 'dbo 上执行 alter .GetTableFromDelimitedValues',因为它是不兼容的对象类型。
嗨
以上是关于在 SQL 中创建和更改表值函数时对象类型不兼容的主要内容,如果未能解决你的问题,请参考以下文章