利用OBJECT_DEFINITION函数来代码存档
作为一名数据库管理员,在进行代码迁移之前,总是尽力给提交于开发环境的代码一个完整的面貌。但是,不得不承认,我不能保证不发生任何可能破坏开发系统的事情。当这种情况发生时,可能的补救措施是恢复到目标代码的前一版本,目标代码可能是存储过程、函数等等。
如果可能的话,你不想做但又不得不做的事情是从备份的数据库中恢复代码,但是如果备份的数据库存储在磁带上,这种方法可能因花费太长的时间而不能使用。如果数据库庞大的话,要花费相当长的时间来恢复,更不用说你还要找一台足够大的服务器来存储备份的文件。不过,还有更好的方法。
很久前我找到的一种解决方法是备份数据库代码到一个独立的数据表中,这样如果在我们开发的代码发生错误时,就可以从数据表恢复出错的过程或函数。这种方法确实节省了大量的时间。
在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这个新函数,你最好亲自试一下。然而,在你的开发环境中设置一些代码备份系统,这样做的重要性在怎么强调也不为过。实际上,我拥有一个类似的备份系统用于我们的开发环境。
如果你能设置一个类似本文提到的恢复系统,就可以进行本地或远程备份你的过程代码,当需要恢复代码时,你将会很方便地进行,而不再用查找备份文件已找到所要恢复的代码。
利用OBJECT_DEFINITION函数来代码存档的更多相关文章
- 利用JavaScript函数对字符串进行加密
加密.解密问题对我来说一直是很神秘的,感到神奇无比. 理论了解 前段时间看到关于利用JavaScript函数unescape()和escape()对字符串进行替换处理.通过查资料得知, escape( ...
- 【编程题目】请修改 append 函数,利用这个函数实现两个非降序链表的并集
42.请修改 append 函数,利用这个函数实现(链表):两个非降序链表的并集,1->2->3 和 2->3->5 并为 1->2->3->5另外只能输出结 ...
- PHP获取毫秒时间戳,利用microtime()函数
PHP获取毫秒时间戳,利用microtime()函数 php本身没有提供返回毫秒数的函数,但提供了一个microtime()函数,借助此函数,可以很容易定义一个返回毫秒数的函数.php的毫秒是没有默认 ...
- 20145311利用gdb调试汇编代码
利用GDB调试汇编代码 首先编写c语言原代码,我使用的是同学分析过的代码 #include<stdio.h>short addend1 = 1;static int addend2 = 2 ...
- (转)Java程序利用main函数中args参数实现参数的传递
Java程序利用main函数中args参数实现参数的传递 1.运行Java程序的同时,可以通过输入参数给main函数中的接收参数数组args[],供程序内部使用!即当你在Java命令行后面带上参数,J ...
- 利用freopen()函数和fc命令简化程序调试
大家在参加ACM比赛或者参加c/c++实验技能竞赛的时候,如果遇到大量的输入和大量的输出时,调试起来很不方便.一来如果结果不正确的话,需要重复输入大量数据:二来如果大量输出的话,得仔细检查输出结果与正 ...
- 利用copy函数简单快速输出/保存vector向量容器中的数据
如果要输出vector中的数据我们可以通过循环语句输出,更加简便的方法是利用copy函数直接输出,例子: #include "stdafx.h" #include <iost ...
- 让 Python 的1、数据库查询返回字典记录--- 2、利用zip函数将两个列表(list)组成字典(dict)
让 Python 的数据库查询返回字典记录: https://yanbin.blog/python-database-query-return-dictionary-result/#more-9179 ...
- 利用foo函数的Bof漏洞攻击:构造攻击字符串
利用foo函数的Bof漏洞攻击:构造攻击字符串 一.基础知识储备 objdump反汇编指令.gdb函数调试运行.Perl语言.|管道符 二.实验步骤 1. 通过反汇编了解程序功能及代码 ①反汇编查看文 ...
随机推荐
- JavaScript表单项数据过滤代码
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"% ...
- java之JMX
java之JMX 有关JMX的定义和架构就不具体解释了.见百度百科: http://baike.baidu.com/link? url=6QzGGEqphTmpft3ll5mXmDNVRdvLRZhk ...
- c++笔试题:不使用第三个变量来交换俩个变量的数值
题目:将a 与 b的值互换. 通常我们的做法是(尤其是在学习阶段):定义一个新的变量,借助它完成交换.代码如下: int a,b; a; b: int t; t ...
- C#开发 —— 基础知识
C# 用于开发可以运行在 .Net 平台上的应用程序,C# 本身只是一种语言,尽管它是用于生成面向 .Net 环境的代码,但它本身不是 .Net 的一部分 Console.WriteLine 命名空间 ...
- OpenCV —— ROI
通过 cvResetImageRoI 函数释放ROI是非常重要的,否则其他操作将默认在ROI区域中进行 通过巧妙的使用widthStep,可以达到同ROI一样的效果 —— 如果想设置和保持一副图像的多 ...
- JavaScript笔记(2)
-->变量的定义 1.取得并使用值是所有程序设计中的要点 2.JS中的变量是没有类型的,在JS中只有值才持有类型,变量所持有的是其对应值的类型. 3.变量的取名要符合标识符的规则: (1)一个J ...
- SICP 习题 (1.39)解题总结
SICP 习题1.39沿着习题1.37, 1.38的方向继续前行,要求我们依据德国数学家J.H.Lambert的公式定义tan-cf过程,用于计算正切函数的近似值. J.H.Lambert的公式例如以 ...
- EasyUI——DataGrid中嵌入Radio
前一篇博客写到项目中的广告位管理,当时没有写到今天的问题,这个问题当时也是困扰我好久. 经过自己的努力和同志们的帮助,最后最终解决. 实现要求把全部的广告位后面的单选button设成一组,目的是一个广 ...
- 可重入锁ReentrantLock--转载
突然被问到什么是可重入锁?脑袋里闪过了n中概念,最终没有找到,从网上学习一下. 原文地址:https://www.ibm.com/developerworks/cn/java/j-jtp10264/ ...
- HttpUtility.UrlEncode 方法 (String) 对 URL 字符串进行编码 NET Framework 4.6 and 4.5
对 URL 字符串进行编码. 这些方法重载可用于对整个 URL(包括查询字符串值)进行编码. 要编码或解码 Web 应用程序之外的值,请使用 WebUtility 类. 重载此成员.有关此成员的完整信 ...