破解SQL2005(SQL2008)的存储过程的存储过程

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介: SQLServer2005里使用with encryption选项创建的存储过程仍然和sqlserver2000里一样,都是使用XOR进行了的加密。和2000不一样的是,在2005的系统表syscomments里已经查不到加密过的密文了。

问题一: DAC连接问题

自己尝试了n次,最后总结一下连接步骤:

1 先用有sysadmin角色的用户登陆SQL Server Management Studio;

2 在工具栏上选数据库引擎查询;服务器名称改为 ADMIN:服务器名称 ;选项>连接属性>连接到数据库 改为加密存储过程所在的数据库;连接

3 运行解密的存储过程;

问题二: 可用的存储过程解密代码

SQLServer2005里怎样对使用with encryption选项创建的存储过程解密

--王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com
--原帖地址

SQLServer2005里使用with encryption选项创建的存储过程仍然和sqlserver2000里一样,都是使用XOR进行了的加密。和2000不一样的是,在2005的系统表syscomments里已经查不到加密过的密文了。要查密文必须使用DAC(专用管理员连接)连接到数据库后,在系统表sys.sysobjvalues查询,该表的列imageval存储了相应的密文。具体可以使用下面的查询:

SELECT imageval FROM sys.sysobjvalues WHERE objid = object_id(@procedure) AND 
valclass = 1 AND subobjid = 1

下面是解密的存储过程,具体代码如下(这是版本4.0,最新的,修正很长的存储过程解密出来是空白的问题):


None.gif Create  PROCEDURE  [ dbo ]. [ sp__windbi$decrypt ]
None.gif( @procedure sysname  =  NULL@revfl  int  =  1)
None.gif AS
ExpandedBlockStart.gif /*
InBlock.gif王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com
InBlock.gif调用形式为:
InBlock.gifexec dbo.sp__windbi$decrypt @procedure,0
InBlock.gif如果第二个参数使用1的话,会给出该存储过程的一些提示。
InBlock.gif--版本4.0  修正存储过程过长解密出来是空白的问题
ExpandedBlockEnd.gif
*/

None.gif SET NOCOUNT  ON
None.gif IF  @revfl  =  1
None.gif BEGIN
None.gif PRINT  ' 警告:该存储过程会删除并重建原始的存储过程。 '
None.gif PRINT  '  在运行该存储过程之前确保你的数据库有一个备份。 '
None.gif PRINT  '  该存储过程通常应该运行在产品环境的一个备份的非产品环境下。 '
None.gif PRINT  '  为了运行这个存储过程,将参数@refl的值更改为0。 '
None.gif RETURN  0
None.gif END
None.gif DECLARE  @intProcSpace  bigint@t  bigint@maxColID  smallint, @procNameLength  int
None.gif select  @maxColID  =  max(subobjid)  FROM
None.gifsys.sysobjvalues  WHERE objid  =  object_id( @procedure)
None.gif -- select @maxColID as 'Rows in sys.sysobjvalues'
None.gif
select  @procNameLength  =  datalength( @procedure+  29
None.gif DECLARE  @real_01  nvarchar( max)
None.gif DECLARE  @fake_01  nvarchar( max)
None.gif DECLARE  @fake_encrypt_01  nvarchar( max)
None.gif DECLARE  @real_decrypt_01  nvarchar( max), @real_decrypt_01a  nvarchar( max)
None.gif declare  @objtype  varchar( 2), @ParentName  nvarchar( max)
None.gif select  @real_decrypt_01a  =  ''
None.gif -- 提取对象的类型如是存储过程还是函数,如果是触发器,还要得到其父对象的名称
None.gif
select  @objtype =type, @parentname = object_name(parent_object_id)
None.gif from sys.objects  where  [ object_id ] = object_id( @procedure)
None.gif --  从sys.sysobjvalues里提出加密的imageval记录
None.gif
SET  @real_01 =( SELECT  top  1 imageval  FROM sys.sysobjvalues  WHERE objid  =
None.gif object_id( @procedureand valclass  =  1  order  by subobjid)
None.gif
None.gif -- 创建一个临时表
None.gif
create  table #output (  [ ident ]  [ int ]  IDENTITY ( 11NOT  NULL ,
None.gif [ real_decrypt ]  NVARCHAR( MAX) )
None.gif -- 开始一个事务,稍后回滚
None.gif
BEGIN  TRAN
None.gif -- 更改原始的存储过程,用短横线替换
None.gif
if  @objtype = ' P '
None.gif   SET  @fake_01 = ' ALTER PROCEDURE  ' +  @procedure  + '  WITH ENCRYPTION AS select 1
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif else  if  @objtype = ' FN '
None.gif   SET  @fake_01 = ' ALTER FUNCTION  ' +  @procedure  + ' () RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ END '
None.gif else  if  @objtype = ' V '
None.gif   SET  @fake_01 = ' ALTER view  ' +  @procedure  + '  WITH ENCRYPTION AS select 1 as col
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif else  if  @objtype = ' TR '
None.gif   SET  @fake_01 = ' ALTER trigger  ' +  @procedure  + '  ON  ' + @parentname + ' WITH ENCRYPTION AFTER INSERT AS RAISERROR ( '' N '' ,16,10)
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif EXECUTE ( @fake_01)
None.gif -- 从sys.sysobjvalues里提出加密的假的
None.gif
SET  @fake_encrypt_01 =( SELECT  top  1 imageval  FROM sys.sysobjvalues  WHERE objid  =
None.gif object_id( @procedureand valclass  =  1  order  by subobjid )
None.gif if  @objtype = ' P '
None.gif   SET  @fake_01 = ' Create PROCEDURE  ' +  @procedure  + '  WITH ENCRYPTION AS select 1
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif else  if  @objtype = ' FN '
None.gif   SET  @fake_01 = ' CREATE FUNCTION  ' +  @procedure  + ' () RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ END '
None.gif else  if  @objtype = ' V '
None.gif   SET  @fake_01 = ' Create view  ' +  @procedure  + '  WITH ENCRYPTION AS select 1 as col
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif else  if  @objtype = ' TR '
None.gif   SET  @fake_01 = ' Create trigger  ' +  @procedure  + '  ON  ' + @parentname + ' WITH ENCRYPTION AFTER INSERT AS RAISERROR ( '' N '' ,16,10)
None.gif  /*
' + REPLICATE( cast( ' * ' as  nvarchar( max)),  datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif -- 开始计数
None.gif
SET  @intProcSpace = 1
None.gif -- 使用字符填充临时变量
None.gif
SET  @real_decrypt_01  =  replicate( cast( ' A ' as  nvarchar( max)), ( datalength( @real_01/ 2 ))
None.gif -- 循环设置每一个变量,创建真正的变量
None.gif--
每次一个字节
None.gif
SET  @intProcSpace = 1
None.gif -- 如有必要,遍历每个@real_xx变量并解密
None.gif
WHILE  @intProcSpace <=( datalength( @real_01) / 2)
None.gif BEGIN
None.gif -- 真的和假的和加密的假的进行异或处理
None.gif
SET  @real_decrypt_01  =  stuff( @real_decrypt_01@intProcSpace1,
None.gif NCHAR( UNICODE( substring( @real_01@intProcSpace1))  ^
None.gif( UNICODE( substring( @fake_01@intProcSpace1))  ^
None.gif UNICODE( substring( @fake_encrypt_01@intProcSpace1)))))
None.gif SET  @intProcSpace = @intProcSpace + 1
None.gif END
None.gif
None.gif
None.gif -- 通过sp_helptext逻辑向表#output里插入变量
None.gif
insert #output (real_decrypt)  select  @real_decrypt_01
None.gif -- select real_decrypt AS '#output chek' from #output --测试
None.gif--
 -------------------------------------
None.gif--
开始从sp_helptext提取
None.gif--
 -------------------------------------
None.gif
declare  @dbname sysname
None.gif, @BlankSpaceAdded  int
None.gif, @BasePos  int
None.gif, @CurrentPos  int
None.gif, @TextLength  int
None.gif, @LineId  int
None.gif, @AddOnLen  int
None.gif, @LFCR  int  -- 回车换行的长度
None.gif
, @DefinedLength  int
None.gif, @SyscomText  nvarchar( max)
None.gif, @Line  nvarchar( 255)
None.gif Select  @DefinedLength  =  255
None.gif SELECT  @BlankSpaceAdded  =  0  -- 跟踪行结束的空格。注意Len函数忽略了多余的空格
None.gif
CREATE  TABLE #CommentText
None.gif(LineId  int
None.gif, Text  nvarchar( 255) collate database_default)
None.gif -- 使用#output代替sys.sysobjvalues
None.gif
DECLARE ms_crs_syscom  CURSOR LOCAL
None.gif FOR  SELECT real_decrypt  from #output
None.gif ORDER  BY ident
None.gif FOR  READ  ONLY
None.gif -- 获取文本
None.gif
SELECT  @LFCR  =  2
None.gif SELECT  @LineId  =  1
None.gif OPEN ms_crs_syscom
None.gif FETCH  NEXT  FROM ms_crs_syscom  into  @SyscomText
None.gif WHILE  @@fetch_status  >=  0
None.gif BEGIN
None.gif SELECT  @BasePos  =  1
None.gif SELECT  @CurrentPos  =  1
None.gif SELECT  @TextLength  =  LEN( @SyscomText)
None.gif WHILE  @CurrentPos  !=  0
None.gif BEGIN
None.gif -- 通过回车查找行的结束
None.gif
SELECT  @CurrentPos  =  CHARINDEX( char( 13) + char( 10),  @SyscomText,
None.gif @BasePos)
None.gif -- 如果找到回车
None.gif
IF  @CurrentPos  !=  0
None.gif BEGIN
None.gif -- 如果@Lines的长度的新值比设置的大就插入@Lines目前的内容并继续
None.gif
While ( isnull( LEN( @Line), 0+  @BlankSpaceAdded  +
None.gif @CurrentPos - @BasePos  +  @LFCR>  @DefinedLength
None.gif BEGIN
None.gif SELECT  @AddOnLen  =  @DefinedLength -( isnull( LEN( @Line), 0+
None.gif @BlankSpaceAdded)
None.gif INSERT #CommentText  VALUES
None.gif@LineId,
None.gif isnull( @Line, N ''+  isnull( SUBSTRING( @SyscomText,
None.gif @BasePos@AddOnLen), N ''))
None.gif SELECT  @Line  =  NULL@LineId  =  @LineId  +  1,
None.gif @BasePos  =  @BasePos  +  @AddOnLen@BlankSpaceAdded  =  0
None.gif END
None.gif SELECT  @Line  =  isnull( @Line, N ''+
None.gif isnull( SUBSTRING( @SyscomText@BasePos@CurrentPos - @BasePos  +  @LFCR), N '')
None.gif SELECT  @BasePos  =  @CurrentPos + 2
None.gif INSERT #CommentText  VALUES@LineId@Line )
None.gif SELECT  @LineId  =  @LineId  +  1
None.gif SELECT  @Line  =  NULL
None.gif END
None.gif ELSE
None.gif -- 如果回车没找到
None.gif
BEGIN
None.gif IF  @BasePos  <=  @TextLength
None.gif BEGIN
None.gif -- 如果@Lines长度的新值大于定义的长度
None.gif
While ( isnull( LEN( @Line), 0+  @BlankSpaceAdded  +
None.gif @TextLength - @BasePos + 1 )  >  @DefinedLength
None.gif BEGIN
None.gif SELECT  @AddOnLen  =  @DefinedLength  -
None.gif( isnull( LEN( @Line), 0+  @BlankSpaceAdded)
None.gif INSERT #CommentText  VALUES
None.gif@LineId,
None.gif isnull( @Line, N ''+  isnull( SUBSTRING( @SyscomText,
None.gif @BasePos@AddOnLen), N ''))
None.gif SELECT  @Line  =  NULL@LineId  =  @LineId  +  1,
None.gif @BasePos  =  @BasePos  +  @AddOnLen@BlankSpaceAdded  =
None.gif 0
None.gif END
None.gif SELECT  @Line  =  isnull( @Line, N ''+
None.gif isnull( SUBSTRING( @SyscomText@BasePos@TextLength - @BasePos + 1 ), N '')
None.gif if  LEN( @Line<  @DefinedLength  and  charindex( '   ',
None.gif @SyscomText@TextLength + 1 )  >  0
None.gif BEGIN
None.gif SELECT  @Line  =  @Line  +  '   '@BlankSpaceAdded  =  1
None.gif END
None.gif END
None.gif END
None.gif END
None.gif FETCH  NEXT  FROM ms_crs_syscom  into  @SyscomText
None.gif END
None.gif IF  @Line  is  NOT  NULL
None.gif INSERT #CommentText  VALUES@LineId@Line )
None.gif select  Text  from #CommentText  order  by LineId
None.gif CLOSE ms_crs_syscom
None.gif DEALLOCATE ms_crs_syscom
None.gif DROP  TABLE #CommentText
None.gif --  -------------------------------------
None.gif--
结束从sp_helptext提取
None.gif--
 -------------------------------------
None.gif--
删除用短横线创建的存储过程并重建原始的存储过程
None.gif
ROLLBACK  TRAN
None.gif DROP  TABLE #output
None.gif go
None.gif


None.gif ALTER  PROCEDURE  [ dbo ]. [ sp__windbi$decrypt ]
None.gif( @procedure sysname  =  NULL@revfl  int  =  1)
None.gif AS
ExpandedBlockStart.gif /*
InBlock.gif王成辉翻译整理,转贴请注明出自微软BI开拓者www.windbi.com
InBlock.gif目前这个存储过程只能解密存储过程,至于解密函数、触发器、视图的存储过程本网站会进一步关注,调用形式为:
InBlock.gifexec dbo.sp__windbi$decrypt @procedure,0
InBlock.gif如果第二个参数使用1的话,会给出该存储过程的一些提示。
InBlock.gif--版本2.0
ExpandedBlockEnd.gif
*/

None.gif SET NOCOUNT  ON
None.gif IF  @revfl  =  1
None.gif BEGIN
None.gif PRINT  ' 警告:该存储过程会删除并重建原始的存储过程。 '
None.gif PRINT  '  在运行该存储过程之前确保你的数据库有一个备份。 '
None.gif PRINT  '  该存储过程通常应该运行在产品环境的一个备份的非产品环境下。 '
None.gif PRINT  '  为了运行这个存储过程,将参数@refl的值更改为0。 '
None.gif RETURN  0
None.gif END
None.gif DECLARE  @intProcSpace  bigint@t  bigint@maxColID  smallint, @intEncrypted 
None.gif tinyint, @procNameLength  int
None.gif select  @maxColID  =  max(subobjid), @intEncrypted  = imageval  FROM 
None.gifsys.sysobjvalues  WHERE objid  =  object_id( @procedure)
None.gif GROUP  BY imageval
None.gif -- select @maxColID as 'Rows in sys.sysobjvalues'
None.gif
select  @procNameLength  =  datalength( @procedure+  29
None.gif DECLARE  @real_01  nvarchar( max)
None.gif DECLARE  @fake_01  nvarchar( max)
None.gif DECLARE  @fake_encrypt_01  nvarchar( max)
None.gif DECLARE  @real_decrypt_01  nvarchar( max), @real_decrypt_01a  nvarchar( max)
None.gif declare  @objtype  varchar( 2), @ParentName  nvarchar( max)
None.gif select  @real_decrypt_01a  =  ''
None.gif -- 提取对象的类型如是存储过程还是函数,如果是触发器,还要得到其父对象的名称
None.gif
select  @objtype =type, @parentname = object_name(parent_object_id)
None.gif from sys.objects  where  [ object_id ] = object_id( @procedure)
None.gif --  从sys.sysobjvalues里提出加密的imageval记录
None.gif
SET  @real_01 =( SELECT  top  1 imageval  FROM sys.sysobjvalues  WHERE objid  = 
None.gif object_id( @procedureand valclass  =  1  order  by subobjid)
None.gif -- 创建一个临时表
None.gif
create  table #output (  [ ident ]  [ int ]  IDENTITY ( 11NOT  NULL ,
None.gif [ real_decrypt ]  NVARCHAR( MAX) )
None.gif -- 开始一个事务,稍后回滚
None.gif
BEGIN  TRAN
None.gif -- 更改原始的存储过程,用短横线替换
None.gif
if  @objtype = ' P '
None.gif   SET  @fake_01 = ' ALTER PROCEDURE  ' +  @procedure  + '  WITH ENCRYPTION AS 
None.gif  
' + REPLICATE( ' - '40003  -  @procNameLength)
None.gif else  if  @objtype = ' FN '
None.gif   SET  @fake_01 = ' ALTER FUNCTION  ' +  @procedure  + ' () RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1 
None.gif  /*
' + REPLICATE( ' * 'datalength( @real_01/ 2  -  @procNameLength) + ' */ END '
None.gif else  if  @objtype = ' V '
None.gif   SET  @fake_01 = ' ALTER view  ' +  @procedure  + '  WITH ENCRYPTION AS select 1 as col
None.gif  /*
' + REPLICATE( ' * 'datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif else  if  @objtype = ' TR '
None.gif   SET  @fake_01 = ' ALTER trigger  ' +  @procedure  + '  ON  ' + @parentname + '  WITH ENCRYPTION AFTER INSERT AS RAISERROR ( '' N '' ,16,10)
None.gif  /*
' + REPLICATE( ' * 'datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif EXECUTE ( @fake_01)
None.gif -- 从sys.sysobjvalues里提出加密的假的
None.gif
SET  @fake_encrypt_01 =( SELECT  top  1 imageval  FROM sys.sysobjvalues  WHERE objid  = 
None.gif object_id( @procedureand valclass  =  1  order  by subobjid )
None.gif if  @objtype = ' P '
None.gif   SET  @fake_01 = ' Create PROCEDURE  ' +  @procedure  + '  WITH ENCRYPTION AS 
None.gif  
' + REPLICATE( ' - '40003  -  @procNameLength)
None.gif else  if  @objtype = ' FN '
None.gif   SET  @fake_01 = ' CREATE FUNCTION  ' +  @procedure  + ' () RETURNS INT WITH ENCRYPTION AS BEGIN RETURN 1 
None.gif  /*
' + REPLICATE( ' * 'datalength( @real_01/ 2  -  @procNameLength) + ' */ END '
None.gif else  if  @objtype = ' V '
None.gif   SET  @fake_01 = ' Create view  ' +  @procedure  + '  WITH ENCRYPTION AS select 1 as col
None.gif  /*
' + REPLICATE( ' * 'datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif else  if  @objtype = ' TR '
None.gif   SET  @fake_01 = ' Create trigger  ' +  @procedure  + '  ON  ' + @parentname + '  WITH ENCRYPTION AFTER INSERT AS RAISERROR ( '' N '' ,16,10)
None.gif  /*
' + REPLICATE( ' * 'datalength( @real_01/ 2  -  @procNameLength) + ' */ '
None.gif -- 开始计数
None.gif
SET  @intProcSpace = 1
None.gif -- 使用字符填充临时变量
None.gif
SET  @real_decrypt_01  =  replicate(N ' A ', ( datalength( @real_01/ 2 ))
None.gif -- 循环设置每一个变量,创建真正的变量
None.gif--
每次一个字节
None.gif
SET  @intProcSpace = 1
None.gif -- 如有必要,遍历每个@real_xx变量并解密
None.gif
WHILE  @intProcSpace <=( datalength( @real_01) / 2)
None.gif BEGIN
None.gif -- 真的和假的和加密的假的进行异或处理
None.gif
SET  @real_decrypt_01  =  stuff( @real_decrypt_01@intProcSpace1,
None.gif NCHAR( UNICODE( substring( @real_01@intProcSpace1))  ^
None.gif( UNICODE( substring( @fake_01@intProcSpace1))  ^
None.gif UNICODE( substring( @fake_encrypt_01@intProcSpace1)))))
None.gif SET  @intProcSpace = @intProcSpace + 1
None.gif END
None.gif -- 通过sp_helptext逻辑向表#output里插入变量
None.gif
insert #output (real_decrypt)  select  @real_decrypt_01
None.gif --  select real_decrypt AS '#output chek' from #output --测试
None.gif--
 -------------------------------------
None.gif--
开始从sp_helptext提取
None.gif--
 -------------------------------------
None.gif
declare  @dbname sysname
None.gif, @BlankSpaceAdded  int
None.gif, @BasePos  int
None.gif, @CurrentPos  int
None.gif, @TextLength  int
None.gif, @LineId  int
None.gif, @AddOnLen  int
None.gif, @LFCR  int  -- 回车换行的长度
None.gif
, @DefinedLength  int
None.gif, @SyscomText  nvarchar( 4000)
None.gif, @Line  nvarchar( 255)
None.gif Select  @DefinedLength  =  255
None.gif SELECT  @BlankSpaceAdded  =  0  -- 跟踪行结束的空格。注意Len函数忽略了多余的空格
None.gif
CREATE  TABLE #CommentText
None.gif(LineId  int
None.gif, Text  nvarchar( 255) collate database_default)
None.gif -- 使用#output代替sys.sysobjvalues
None.gif
DECLARE ms_crs_syscom  CURSOR LOCAL
None.gif FOR  SELECT real_decrypt  from #output
None.gif ORDER  BY ident
None.gif FOR  READ  ONLY
None.gif -- 获取文本
None.gif
SELECT  @LFCR  =  2
None.gif SELECT  @LineId  =  1
None.gif OPEN ms_crs_syscom
None.gif FETCH  NEXT  FROM ms_crs_syscom  into  @SyscomText
None.gif WHILE  @@fetch_status  >=  0
None.gif BEGIN
None.gif SELECT  @BasePos  =  1
None.gif SELECT  @CurrentPos  =  1
None.gif SELECT  @TextLength  =  LEN( @SyscomText)
None.gif WHILE  @CurrentPos  !=  0
None.gif BEGIN
None.gif -- 通过回车查找行的结束
None.gif
SELECT  @CurrentPos  =  CHARINDEX( char( 13) + char( 10),  @SyscomText
None.gif @BasePos)
None.gif -- 如果找到回车
None.gif
IF  @CurrentPos  !=  0
None.gif BEGIN
None.gif -- 如果@Lines的长度的新值比设置的大就插入@Lines目前的内容并继续
None.gif
While ( isnull( LEN( @Line), 0+  @BlankSpaceAdded  + 
None.gif @CurrentPos - @BasePos  +  @LFCR>  @DefinedLength
None.gif BEGIN
None.gif SELECT  @AddOnLen  =  @DefinedLength -( isnull( LEN( @Line), 0+ 
None.gif @BlankSpaceAdded)
None.gif INSERT #CommentText  VALUES
None.gif@LineId,
None.gif isnull( @Line, N ''+  isnull( SUBSTRING( @SyscomText
None.gif @BasePos@AddOnLen), N ''))
None.gif SELECT  @Line  =  NULL@LineId  =  @LineId  +  1,
None.gif @BasePos  =  @BasePos  +  @AddOnLen@BlankSpaceAdded  =  0
None.gif END
None.gif SELECT  @Line  =  isnull( @Line, N ''+ 
None.gif isnull( SUBSTRING( @SyscomText@BasePos@CurrentPos - @BasePos  +  @LFCR), N '')
None.gif SELECT  @BasePos  =  @CurrentPos + 2
None.gif INSERT #CommentText  VALUES@LineId@Line )
None.gif SELECT  @LineId  =  @LineId  +  1
None.gif SELECT  @Line  =  NULL
None.gif END
None.gif ELSE
None.gif -- 如果回车没找到
None.gif
BEGIN
None.gif IF  @BasePos  <=  @TextLength
None.gif BEGIN
None.gif -- 如果@Lines长度的新值大于定义的长度
None.gif
While ( isnull( LEN( @Line), 0+  @BlankSpaceAdded  + 
None.gif @TextLength - @BasePos + 1 )  >  @DefinedLength
None.gif BEGIN
None.gif SELECT  @AddOnLen  =  @DefinedLength  - 
None.gif( isnull( LEN( @Line), 0+  @BlankSpaceAdded)
None.gif INSERT #CommentText  VALUES
None.gif@LineId,
None.gif isnull( @Line, N ''+  isnull( SUBSTRING( @SyscomText
None.gif @BasePos@AddOnLen), N ''))
None.gif SELECT  @Line  =  NULL@LineId  =  @LineId  +  1,
None.gif @BasePos  =  @BasePos  +  @AddOnLen@BlankSpaceAdded  = 
None.gif 0
None.gif END
None.gif SELECT  @Line  =  isnull( @Line, N ''+ 
None.gif isnull( SUBSTRING( @SyscomText@BasePos@TextLength - @BasePos + 1 ), N '')
None.gif if  LEN( @Line<  @DefinedLength  and  charindex( '   '
None.gif @SyscomText@TextLength + 1 )  >  0
None.gif BEGIN
None.gif SELECT  @Line  =  @Line  +  '   '@BlankSpaceAdded  =  1
None.gif END
None.gif END
None.gif END
None.gif END
None.gif FETCH  NEXT  FROM ms_crs_syscom  into  @SyscomText
None.gif END
None.gif IF  @Line  is  NOT  NULL
None.gif INSERT #CommentText  VALUES@LineId@Line )
None.gif select  Text  from #CommentText  order  by LineId
None.gif CLOSE ms_crs_syscom
None.gif DEALLOCATE ms_crs_syscom
None.gif DROP  TABLE #CommentText
None.gif --  -------------------------------------
None.gif--
结束从sp_helptext提取
None.gif--
 -------------------------------------
None.gif--
删除用短横线创建的存储过程并重建原始的存储过程
None.gif
ROLLBACK  TRAN
None.gif DROP  TABLE #output
目录
相关文章
|
3月前
|
SQL 存储 关系型数据库
sql语句,索引,视图,存储过程
sql语句,索引,视图,存储过程
30 0
|
3月前
|
存储 SQL 缓存
4.2.1 SQL语句、索引、视图、存储过程
4.2.1 SQL语句、索引、视图、存储过程
|
1月前
|
存储 SQL 数据库
sql serve存储过程
sql serve存储过程
14 0
|
1月前
|
SQL 网络协议 Windows
破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”
破解SQL Server迷局,彻底解决“管道的另一端无任何进程错误233”
|
1月前
|
存储 SQL
物料清单应用输入模板的SQL存储过程设计
物料清单应用输入模板的SQL存储过程设计
|
3月前
|
存储 SQL Oracle
PL/SQL存储过程的使用
PL/SQL存储过程的使用
66 1
|
4月前
|
存储 SQL Oracle
|
4月前
|
存储 SQL 定位技术
数据库基础(六):T-SQL语言程序设计、游标定义与使用及存储过程创建与信息查找
数据库基础(六):T-SQL语言程序设计、游标定义与使用及存储过程创建与信息查找
|
9月前
|
存储 SQL 安全
数据库SQL Server 9-10 章(存储过程与触发器)
数据库SQL Server 9-10 章(存储过程与触发器)
150 0
|
4月前
|
存储 SQL 数据库
数据库第十二次作业 存储过程(PL/SQL语句集)的应用
数据库第十二次作业 存储过程(PL/SQL语句集)的应用
31 0

热门文章

最新文章