2010-10-27 32 views
2

使用SQL Server 2008,我想創建一個UDF,它爲我提供了一個對象的創建日期。這是代碼:如何在引用調用方中正確的sys.objects表的另一個數據庫中創建UDF或View?

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在主數據庫或其他一些共享的數據庫,以便它是從任何地方訪問,但如果我這樣做,則sys.objects參考從拉master數據庫而不是我從中啓動我的查詢的數據庫。我知道你可以這樣做,因爲information_schema視圖位於master,只是將調用包裝到本地sys.objects實例,所以我希望有一個簡單的方法可以用我的UDF來完成。

+0

的'information_schema'視圖中的每個數據庫在本地創建。另外,作爲一般規則,主數據庫應該保持獨立。創建一個「實用工具」數據庫來保存這樣的東西。 – 2010-10-27 16:00:47

+0

你可以自己看看。在SSMS中,深入查看數據庫 - > YourDatabase - >視圖 - >系統視圖。 – 2010-10-27 16:06:21

+0

這是行不通的。實用程序中的UDF只會訪問實用程序中的sys.objects,而不是調用數據庫。忽略主控部分,如果這是你的掛斷......我需要來自調用者的sys.objects,而不是UDF託管的db。 – mattmc3 2010-10-27 16:06:51

回答

4

爲什麼不這樣做呢?

  1. 創建在創建包含所有從服務器上的每個數據庫中sys.objects的信息的主數據庫的圖的存儲過程。
  2. 每當創建一個數據庫執行CREATEALTERDROP語句被炒魷魚一個DDL Trigger。然後觸發器將在步驟#1中執行存儲過程。這允許視圖自動更新。
  3. (可選)創建一個用戶定義的函數,該函數查詢給定對象的創建日期的視圖。

存儲過程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'; 
+0

這絕對是光滑的。我遇到的唯一問題是我有太多的@CreateView變量的數據庫來保存整個腳本,但是爲了我想要做的事情,這將解決它。謝謝! – mattmc3 2012-11-09 14:21:21

+1

太棒了,很高興它幫助!如果您需要額外的容量,您應該能夠將'@ CreateView'變量從'varchar(8000)'更改爲'nvarchar(max)'。 – Alexander 2012-11-09 14:25:37

1

好像有一個未公開的存儲過程,使您可以創建自己的系統對象:sp_ms_marksystemobject

你可以閱讀更多的http://www.mssqltips.com/tip.asp?tip=1612

+0

那麼近!這似乎很適合存儲過程,但不適用於UDF。還有其他建議嗎? – mattmc3 2010-10-27 17:26:27

+0

這就是我所擁有的一切。對不起:) – KenJ 2010-10-27 17:57:38

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

不幸的是,我特別希望爲UDF提供一個答案,因爲我有更多的用途,而不僅僅是我在這裏介紹的簡單案例。我只是選擇了一個簡單的例子,看看我能否爲更大的目的獲得幫助。 – mattmc3 2010-11-30 15:52:30

4

Jaeell幾乎擁有了。試試這個:

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 
; 
+3

這將不起作用,因爲您不能使用函數中的動態SQL,也不能調用存儲過程。它應該是存儲過程。 – gotqn 2012-11-05 18:54:50

1

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

+0

該文章是關於SQL 2000的。這是否在2012年工作? – mattmc3 2012-11-07 14:53:41

+0

@ mattmc3,yes..this will will – 2012-11-08 03:33:20

+0

@ mattmc3你有什麼成就嗎?如果你準備好了,請分享你的結果: - ] – gotqn 2012-11-08 08:13:25

相關問題