如何在另一个引用调用方中正确的sys.objects表的数据库中创建UDF或View?

时间:2010-10-27 15:39:49

标签: sql-server tsql user-defined-functions

使用SQL Server 2008,我想创建一个UDF,它给我一个对象的创建日期。这是代码:

create function dbo.GetObjCreateDate(@objName sysname) returns datetime as
begin
    declare @result datetime
    select @result = create_date from sys.objects where name = @objname
    return @result
end
go

我想把这个UDF放在master数据库或其他一些共享数据库中,以便可以从任何地方访问它,除非我这样做,sys.objects引用来自master数据库而不是我正在启动我的查询的数据库。我知道你可以这样做,因为information_schema视图位于master并且只是调用sys.objects的本地实例,所以我希望有一个简单的方法可以用我的UDF做到这一点

5 个答案:

答案 0 :(得分:5)

试试这个:

CREATE FUNCTION dbo.GetObjCreateDate(@objName sysname, @dbName sysname) 
RETURNS datetime AS
BEGIN
    DECLARE @createDate datetime;
    DECLARE @params nvarchar(50);
    DECLARE @sql nvarchar(500);

    SET @params = '@createDate datetime OUTPUT';

    SELECT @sql = 'SELECT @createDate = create_date FROM ' + @dbName + '.sys.objects WHERE name = ''' + @objname + '''';

    EXEC sp_executesql @sql, @params, @createDate = @createDate OUTPUT;         

     RETURN @createDate
END
;

答案 1 :(得分:4)

为什么不这样做?

  1. 创建一个存储过程,在master数据库中创建一个视图,其中包含服务器上每个数据库的sys.objects中的所有信息。
  2. 创建一个DDL Trigger,只要对数据库执行CREATEALTERDROP语句,就会触发该{{3}}。然后,触发器将在步骤#1中执行存储过程。这允许视图自动更新。
  3. (可选)创建一个用户定义的函数,用于查询视图以查找给定对象的创建日期。
  4. 存储过程DDL:

    USE [master];
    GO
    
    CREATE PROCEDURE dbo.BuildAllServerObjectsView
    AS
    
    SET NOCOUNT ON;
    
    IF OBJECT_ID('master.dbo.AllServerObjects') IS NOT NULL
        EXEC master..sp_SQLExec 'DROP VIEW dbo.AllServerObjects;';
    
    IF OBJECT_ID('tempdb..Databases') IS NOT NULL
        DROP TABLE #Databases;
    
    DECLARE @CreateView varchar(8000);
    SET @CreateView = 'CREATE VIEW dbo.AllServerObjects AS' + CHAR(13)+CHAR(10) + CHAR(13)+CHAR(10);
    
    SELECT name COLLATE SQL_Latin1_General_CP1_CI_AS AS 'name'
      INTO #Databases
      FROM sys.databases
     ORDER BY name;
    
    DECLARE @DatabaseName nvarchar(100);
    WHILE (SELECT COUNT(*) FROM #Databases) > 0
    BEGIN
        SET @DatabaseName = (SELECT TOP 1 name FROM #Databases ORDER BY name);
        SET @CreateView +='SELECT N'+QUOTENAME(@DatabaseName, '''')+' AS ''database_name''' + CHAR(13)+CHAR(10)
                        + '      ,name COLLATE SQL_Latin1_General_CP1_CI_AS AS ''object_name''' + CHAR(13)+CHAR(10)
                        + '      ,object_id' + CHAR(13)+CHAR(10)
                        + '      ,principal_id' + CHAR(13)+CHAR(10)
                        + '      ,schema_id' + CHAR(13)+CHAR(10)
                        + '      ,parent_object_id' + CHAR(13)+CHAR(10)
                        + '      ,type' + CHAR(13)+CHAR(10)
                        + '      ,type_desc' + CHAR(13)+CHAR(10)
                        + '      ,create_date' + CHAR(13)+CHAR(10)
                        + '      ,modify_date' + CHAR(13)+CHAR(10)
                        + '      ,is_ms_shipped' + CHAR(13)+CHAR(10)
                        + '      ,is_published' + CHAR(13)+CHAR(10)
                        + '      ,is_schema_published' + CHAR(13)+CHAR(10)
                        + '  FROM ' + QUOTENAME(@DatabaseName) + '.sys.objects';
        IF (SELECT COUNT(*) FROM #Databases) > 1
            SET @CreateView += CHAR(13)+CHAR(10) + CHAR(13)+CHAR(10) + ' UNION' + CHAR(13)+CHAR(10);
        ELSE
            SET @CreateView += ';';  
    
        DELETE #Databases
         WHERE name = @DatabaseName;
    END;
    
    --PRINT @CreateView --<== Uncomment this to see the DDL for the view.
    
    EXEC master..sp_SQLExec @CreateView;
    
    IF OBJECT_ID('tempdb..Databases') IS NOT NULL
        DROP TABLE #Databases;
    
    GO
    

    功能DDL:

    USE [master];
    GO
    
    CREATE FUNCTION dbo.GetObjCreateDate(@DatabaseName sysname, @objName sysname) RETURNS DATETIME AS
    BEGIN
        DECLARE @result datetime;
    
        SELECT @result = create_date
          FROM master.dbo.AllServerObjects
         WHERE [database_name] = @DatabaseName
           AND [object_name] = @objname;
    
        RETURN @result;
    END
    GO
    

    样本用法:

    SELECT master.dbo.GetObjCreateDate('MyDatabase', 'SomeObject') AS 'Created';
    SELECT master.dbo.GetObjCreateDate(DB_NAME(), 'spt_monitor') AS 'Created';
    

答案 2 :(得分:2)

它必须是一个功能吗?如果你只是希望它可以在任何地方访问,一个技巧是将你的代码放在varchar和sp_executesql中:

create procedure dbo.GetObjCreateDate(@objName sysname) 
as
    declare @sql nvarchar(max)
    select @sql = 'select create_date from sys.objects where name = ''' + @objname + ''''
    EXEC sp_executesql @sql 
go

答案 3 :(得分:1)

似乎有一个未记录的存储过程允许您创建自己的系统对象:sp_ms_marksystemobject

您可以在http://www.mssqltips.com/tip.asp?tip=1612

上阅读更多内容

答案 4 :(得分:1)

看看How to Write Your Own System Functions。我相信它可以帮到你