利用OBJECT_DEFINITION函数来代码存档
作者:builder.com 发布时间:2009-01-20 15:34:00
作为一名数据库管理员,在进行代码迁移之前,我总是尽力给提交于开发环境的代码一个完整的面貌。但是,不得不承认,我不能保证不发生任何可能破坏开发系统的事情。当这种情况发生时,可能的补救措施是恢复到目标代码的前一版本,目标代码可能是存储过程、函数等等。
如果可能的话,你不想做但又不得不做的事情是从备份的数据库中恢复代码,但是如果备份的数据库存储在磁带上,这种方法可能因花费太长的时间而不能使用。如果数据库庞大的话,要花费相当长的时间来恢复,更不用说你还要找一台足够大的服务器来存储备份的文件。不过,还有更好的方法。
很久前我找到的一种解决方法是备份数据库代码到一个独立的数据表中,这样如果在我们开发的代码发生错误时,就可以从数据表恢复出错的过程或函数。这种方法确实节省了大量的时间。
在SQL Server 2000中,这种方法可以这样实现:对特别的数据库做一个完整的syscomments数据表备份,然后将备份的数据表放入档案表中。我通常保存最近两周的重要过程代码。利用这种技术唯一的麻烦是:如果代码对象十分大,那么可能要对代码进行重构。因为如果代码过大将会被存储到syscomments表中不同的行中,有时这可能是件令人感到头痛的事。
SQL Server 2005 新增加的众多功能之一是可以利用一个系统函数返回某个对象的完整代码,这个系统函数将使得存档你的过程代码变得十分简单。
OBJECT_DEFINITION
SQL Server 2005新增的系统函数OBJECT_DEFINITION根据提供给该函数的对象ID返回对象的TSQL代码。为了更好的理解这个函数的工作过程,让我举个例子。首先我们创建一个用户自定义函数,该函数的脚本如下:
CREATE FUNCTION udf_Multiply
(@Val1 INT,
@Val2 INT
)
RETURNS INT
AS
BEGIN
DECLARE @RetVal INT
SET @RetVal = (@Val1 * @Val2)
RETURN(@RetVal)
END
这是一个很简单的小函数。因为它仅仅处理两个参数,但是已足够为我们演示OBJECT_DEFINITION函数是如何工作。测试该系统函数的脚本如下:
DECLARE @ObjectID INT
SET @ObjectID = OBJECT_ID('udf_Multiply')
SELECT OBJECT_DEFINITION(@ObjectID)
在这个例子中,我们实际上用了两个系统函数。首先,我们要得到前面创建的udf_Multiply函数的OBJECT_ID,在SQL Server 数据库引擎中,OBJECT_ID是一个对象的系统标识符。然后我们将这个ID传给系统函数OBJECT_DEFINITION,这一系统函数将返回提供给它的ID对象的代码,即返回值是我们以前为udf_Multiply 函数写的TSQL代码。
既然我们对OBJECT_DEFINITION函数的工作原理有了很好的了解,接下来让我们看看如何利用这个函数来存档我们数据库中的过程代码。首先,运行列表A中的脚本程序在测试数据库中创建20个存储过程。
DECLARE @i INT
SET @i = 1
WHILE @i <= 20
BEGIN EXECUTE
( 'IF OBJECT_ID(''usp_TestProcedure'+@i + ''')>0
DROP PROCEDURE usp_TestProcedure'+@i+' ' )
EXECUTE ( 'CREATE PROCEDURE usp_TestProcedure' + @i + '
AS BEGIN PRINT ''The name of this procedure is '' +
CAST(OBJECT_NAME(@@PROCID) AS VARCHAR(20)) END' )
SET @i = @i + 1
END
你将看到在上面的脚本中,我们使用了动态SQL语句。当创建动态SQl语句时,我习惯用系统存储过程sp_executesql,因为该过程能够很好地在系统中缓存SQL语句。但是,在我们这一例子中,EXECUTE命令就能很好地完成任务。
现在我们的数据库中已经有了一些对象,我们可以创建用来存档数据库中存储过程需要的对象和代码。在列表B中的脚本可以为我们完成这项工作。
IF OBJECT_ID('CodeArchive','U')>0
DROP TABLE CodeArchive
CREATE TABLE CodeArchive
( ArchiveID INT IDENTITY(1,1) PRIMARY KEY,
ObjectName SYSNAME,
ObjectDescription VARCHAR(60),
ObjectType CHAR(2),
ObjectDefinition VARCHAR(MAX),
ObjectID INT,
CreationDate DATETIME,
ModifiedDate DATETIME,
EntryDate DATETIME DEFAULT(GETDATE())
)
INSERT INTO CodeArchive
( ObjectName, ObjectDescription,
ObjectType, ObjectDefinition,
ObjectID, CreationDate, ModifiedDate
)
SELECT so.name, so.type_desc, so.type,
OBJECT_DEFINITION(object_id),
so.object_id, so.create_date, so.modify_date
FROM sys.objects so
WHERE so.[type]
IN('C', 'D', 'P', 'FN', 'R', 'RF', 'TR', 'IF', 'TF', 'V')
存档方案首先要求有一个用来存储我们定义代码的表格,和在上面的表格脚本中看到的一样,我们将对象定义代码存入表格的ObjectDefinition域,这是一个VARCHAR(MAX)数据类型的域。VARCHAR(MAX)是SQL Server 2005新增的一种数据类型,它可以存储高达2GB的有效数据。这样我们就不在局限于文本数据类型或者将我们的数据保存在一个单个数据页上。这种数据类型存储我们的对象毫无问题。
在上面的脚本中关于插入CodeArchive表有几点值得注意的地方。首先是在查询中包含的数据类型,这些用于OBJECT_DEFINITION函数的对象类型将返回一个值。A列表中包含的。
对象类型列在下面供参考。其次是脚本调用的方法,我通常是利用SQL Server的预定任务调度法执行类似的脚本(你可以按照工作要求反复的运行脚本)。无论用什么调度方法,总之你需要按照一定的规则运行脚本,这样才能在需要时恢复你的过程代码。
OBJECT_DEFINITION函数用到的对象类型列表:
T:检查约束。
D:默认。
P:TSQL存储过程。
FN:TSQL数值用户自定义函数。
R:规则。
RF:复制过滤过程。
TR:TSQL触发器。
IF:TSQL内嵌函数。
TF:TSQL数值函数。
V:视图。
存档需求
希望本文对你有所帮助,如果你还没有使用过OBJECT_DEFINITION这个新函数,你最好亲自试一下。然而,在你的开发环境中设置一些代码备份系统,这样做的重要性在怎么强调也不为过。实际上,我拥有一个类似的备份系统用于我们的开发环境。
如果你能设置一个类似本文提到的恢复系统,就可以进行本地或远程备份你的过程代码,当需要恢复代码时,你将会很方便地进行,而不再用查找备份文件已找到所要恢复的代码。
猜你喜欢
- win7 64位下如何安装配置mysql-5.7.5-m15-winx64 距离上次安装MySQL已经过去好久了。步骤这些,有可能
- 在之前给大家分享过这篇文章:CentOS 7.0下使用yum安装mysql的方法详解,小编觉得不够详细,今天给大家通过本文给大家做个补充,感
- 示例首先模拟一个业务场景,有订单、产品、自定义订单三个结构体,订单中包含多个产品:type Order struct {Id
- import turtle as tt.setup(800,600,0,0,)t.pensize(2)t.speed(1)t.color(&
- PHP attributes() 函数实例返回 XML 的 body 元素的属性和值:<?php $note=<<<
- Python3.7 基于 pycryptodome 的AES加密解密、RSA加密解密、加签验签,具体代码如下所示:#!/usr/bin/en
- 本文实例讲述了Python实现的微信公众号群发图片与文本消息功能。分享给大家供大家参考,具体如下:在微信公众号开发中,使用api都要附加ac
- 创建测试dataframe:>>> import pandas as pd>>> df = pd.Dat
- 本文实例分析了python动态性强类型用法。分享给大家供大家参考。具体如下:Python变量声明和定义与C#不同,Python在使用变量之前
- asp+js做的一个dig程序中的投票(有的叫顶一下,踩一下),由于代码较长,只贴出核心部分:投票中的代码相关文章推荐:ajax +asp
- 1. 目标通过hadoop hive或spark等数据计算框架完成数据清洗后的数据在HDFS上爬虫和机器学习在Python中容易实现在Lin
- 本文实例讲述了js鼠标滑过图片震动特效的方法。分享给大家供大家参考。具体实现方法如下:<html><head><
- 背景:项目中有多个组件调用同一接口,为提高代码可维护性,需要封装公共方法直接return 接口调用的结果export function ge
- 如下所示:import numpy as npimport pandas as pdfrom pandas import Series,Da
- Python中的数据可视化matplotlib 是python最著名的绘图库,它提供了一整套和matlab相似的命令API,十分适合交互式地
- 方法一、os.system() 会保存可执行程序中的打印值和主函数的返回值,且会将执行过程中要打印的内容打印出来import os main
- Pytorch的核心是两个主要特征:1.一个n维tensor,类似于numpy,但是tensor可以在GPU上运行2.搭建和训练神经网络时的
- 详细:1.闵可夫斯基距离(Minkowski Distance)2.欧氏距离(Euclidean Distance)3.曼哈顿距离(Manh
- 反射简介Go语言的反射是通过reflect包提供的,它允许我们在运行时访问接口的动态类型信息和值。其基本的操作包括获取一个类型的Kind(例
- 概述laravel服务容器就像一个高度自动化的工厂,你需要的东西,定制好模型,使用特定接口来制造。因为使用了服务容器,laravel中大部分