为什么我要收到数据库中已经有一个名为'XXX'的对象?

时间:2013-02-27 15:37:42

标签: sql sql-server sql-server-2008

我正在做简单的事情,这是有道理的,

IF EXISTS(SELECT * FROM sysobjects WHERE xtype = 'TF' AND name = 'GetGeographyFromSourceID')
BEGIN
    DROP FUNCTION dbo.GetGeographyFromSourceID
END
GO

CREATE FUNCTION dbo.GetGeographyFromSourceID
(
    @SourceID INT
)
RETURNS  GEOGRAPHY
AS
BEGIN
    DECLARE @Longitude FLOAT = 0; 
    DECLARE @Latitude FLOAT = 0; 
    DECLARE @Geo GEOGRAPHY;

    SELECT  @Longitude = Longitude, 
            @Latitude = Latitude 
    FROM    Sources 
    WHERE   ID = @SourceID; 

    SELECT @Geo = geography::STGeomFromText('POINT(' + CONVERT(VARCHAR( 100), @Longitude) + ' ' + CONVERT( VARCHAR( 100),@Latitude) + ')', 4326);

    RETURN(@Geo)
END

如果存在,则删除它并重新创建它。但我收到错误There is already an object named 'XXX' in the database?

4 个答案:

答案 0 :(得分:5)

您正在测试数据库中是否存在表值函数,但您描述的函数不返回表。在此之前替换代码的第一部分(在开始之前),然后再试一次:

IF EXISTS (
    SELECT * FROM sysobjects WHERE id = object_id(N'GetGeographyFromSourceID') 
    AND xtype IN (N'FN', N'IF', N'TF')
)
    DROP FUNCTION GetGeographyFromSourceID
GO

答案 1 :(得分:4)

看起来它实际上并没有达到你的DROP FUNCTION语句,因为你正在检查只查找表函数的xtype = 'TF',这个函数不是xtype='FN'(标量函数)

MSDN Reference

答案 2 :(得分:3)

将其更改为FN而不是TF

IF EXISTS(SELECT * FROM sysobjects WHERE xtype = 'FN' AND name = 'GetGeographyFromSourceID')
BEGIN
    DROP FUNCTION dbo.GetGeographyFromSourceID
END
GO

CREATE FUNCTION dbo.GetGeographyFromSourceID
(
    @SourceID INT
)
RETURNS  GEOGRAPHY
AS
BEGIN
    DECLARE @Longitude FLOAT = 0; 
    DECLARE @Latitude FLOAT = 0; 
    DECLARE @Geo GEOGRAPHY;

    SELECT  @Longitude = Longitude, 
            @Latitude = Latitude 
    FROM    Sources 
    WHERE   ID = @SourceID; 

    SELECT @Geo = geography::STGeomFromText('POINT(' + CONVERT(VARCHAR( 100), @Longitude) + ' ' + CONVERT( VARCHAR( 100),@Latitude) + ')', 4326);

    RETURN(@Geo)
END

答案 3 :(得分:1)

我知道这已经得到了回答,但只是为了补充一点。考虑到SQL处理对象名称的方式,通常最好不要检查何时使用这种类型的代码。创建对象时,它的名称是唯一的,而不是名称+类型的组合。另外一种更简单的检查方法是使用OBJECT_ID函数。以下是我在master数据库上做的一些例子。

IF (OBJECT_ID('sysobjects') IS NOT NULL)
    PRINT OBJECT_ID('sysobjects')

IF (OBJECT_ID('sys.sysobjects') IS NOT NULL)
    PRINT OBJECT_ID('sys.sysobjects')

IF (OBJECT_ID('xyz') IS NOT NULL)
    PRINT OBJECT_ID('xyz')

前两个将评估为true并运行print(给出相同的对象id),第三个将评估为false而不运行print。