print、sp_helptext的限制与扩展
在SQL中,使用动态SQL是很常见的。有些复杂的计算,或是存储过程,代码很长,中间可能有多次执行SQL语句。而调试拼串的SQL语句却是件痛苦的事,很难看出来运行的语句是什么。所以我会经常使用print这个命令把运行前的语句打印到屏幕上,然后复制出来到另一个窗口进行调试、修改,这样就比较方便了。但是这个print命令有一些限制,在单字节符集下,最大只能打印打印8000个字符的长度,而在双字节字符集是4000个。
以下存储过程可以打印完整的信息,不受长度的限制。代码如下:
IF OBJECT_ID(N'sp_print_all') IS NOT NULL
BEGIN
DROP PROCEDURE sp_print_all
END
GO
CREATE PROCEDURE sp_print_all (@dynamic_sql NVARCHAR(MAX))
AS DECLARE @start INT
DECLARE @len INT
SET @start = 1
SET @len = 4000 WHILE (@start < LEN(@dynamic_sql))
BEGIN
PRINT SUBSTRING(@dynamic_sql, @start, @len)
SET @start = @start + @len
END
PRINT SUBSTRING(@dynamic_sql, @start, @len)
GO
code-1
还有一个存储sp_helptext,可以查询存储过程,函数等代码,使用起来也比较方便,但也有长度的限制,而且打印出来的格式跟源代码的格式有些对应不上。写了一个自定义存储过程来代替,代码如下:
IF OBJECT_ID(N'sp_helptext_user') IS NOT NULL
BEGIN
DROP PROCEDURE sp_helptext_user
END
GO
CREATE PROCEDURE sp_helptext_user(@obj_name NVARCHAR(200) = '')
AS
SET NOCOUNT ON;
DECLARE @text NVARCHAR(MAX)
,@i INT
,@text2 NVARCHAR(MAX)
,@db_name SYSNAME
,@obj_id BIGINT SET @db_name = PARSENAME(@obj_name ,3)
IF @db_name IS NULL
SET @db_name = DB_NAME()
ELSE
IF @db_name <> DB_NAME()
BEGIN
RAISERROR(15250 ,-1 ,-1)
RETURN (1)
END SET @obj_id = OBJECT_ID(@obj_name)
IF @obj_id IS NULL
BEGIN
RAISERROR(15009 ,-1 ,-1 ,@obj_name ,@db_name)
RETURN (1)
END SELECT @text = [definition]
FROM sys.all_sql_modules
WHERE [object_id] = @obj_id WHILE LEN(@text) > 2000
BEGIN
SET @i = CHARINDEX(CHAR(13) ,@text ,2000)
SET @text2 = LEFT(@text ,@i)
SET @text = SUBSTRING(@text ,@i + 2 ,LEN(@text))
PRINT @text2
END
PRINT @text
SET NOCOUNT OFF;
GO
code-2
当然,查看源代码有多种方法,可以在SSMS上操作等,看个人习惯或方便操作了。
print、sp_helptext的限制与扩展的更多相关文章
- 重构sql server的sys.sp_helptext存储
本文目录列表: 1.sys.sp_helptext存储的功能和效果 2.重构sys.sp_helptext存储(命名为dbo.usp_helptext)提供直观的效果 3.sys.sp_helptex ...
- 爬虫之scrapy扩展
针对pipelines的扩展 from scrapy.exceptions import DropItem class CustomPipeline(object): def __init__(sel ...
- swift 学习- 23 -- 扩展
// 扩展 就是为一个已有的 类, 结构体, 枚举, 或者 协议类型添加新功能, 这包括在没有权限获取 原始代码的情况下 扩展类型的能力 (即 逆向建模), 扩展和 OC 中的分类类似, (与 OC ...
- [Swift通天遁地]五、高级扩展-(11)图像加载Loading动画效果的自定义和缓存
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- scrapy的扩展件extensions
extensions.py文件 # -*- coding: utf-8 -*- # 该扩展会在以下事件时记录一条日志: # spider被打开 # spider被关闭 # 爬取了特定数量的条目(ite ...
- Flutter——Dart Extension扩展方法的使用
dart的extension方法可以给已经存在的类添加新的函数,通过extension我们可以封装一些常用方法,提高开发效率. 例一:扩展String 给string添加一个log打印方法 exten ...
- Java 8 的 Nashorn 脚本引擎教程
本文为了解所有关于 Nashorn JavaScript 引擎易于理解的代码例子. Nashorn JavaScript 引擎是Java SE 8的一部分,它与其它像Google V8 (它是Goog ...
- Python【第二章】:Python的数据类型
基本数据类型 一.整型 如: 18.73.84 二.长整型 如:2147483649.9223372036854775807 三.浮点型 如:3.14.2.88 四.字符串 如:'wupeiqi'.' ...
- Python学习【第四篇】用户输入及判断
用户输入: 例1.写一个用户输入密码的小程序,流程如下: 1.用户输入自己的用户名 2.打印"Hello+用户名" #!/usr/bin/env python #name = ra ...
随机推荐
- 简单的词法分析和语法分析(C++实现,CodeBlocks+GCC编译)
说明: 分析的语言是SNL语言,详见<编译程序的设计与实现>( 刘磊.金英.张晶.张荷花.单郸编著) 词法分析就是实现了词法分析的自动机 语法分析使用递归下降法 运行结果: 词法分析 得到 ...
- NYOJ 478
月老的烦恼(1) 描述 月老最近遇到了一个很棘手的问题,就是“剩男”“剩女”急速增长,而自己这边又人手不足导致天天都得加班.现在需要你来帮助月老解决这个问题,牵红绳的规则很简单:每个男生都一个编号n( ...
- TortoiseSVN 中 一个 Merge revisions to.. 小坑
注意: 不能只选头与尾svn号, 一定要全选 !!全选 !!全选 !!
- android第一行代码-2.activity基本用法
摘要: 本节主要涉及到的有activity的创建,标题栏隐藏,button绑定方法(toast的使用),menu使用,活动销毁 1.activity的创建跟注册 创建: public class Te ...
- javascript马赛克遮罩图片切换效果:XMosaic.js(转)
新鲜出炉的javascript图片切换特效,实现的是马赛克遮罩切换.在flash里,好实现遮罩动画很简单,不过JS实现起来就有些困难了. XMosaic.js,与XScroll.js和XScroll2 ...
- [CareerCup] 18.1 Add Two Numbers 两数相加
18.1 Write a function that adds two numbers. You should not use + or any arithmetic operators. 这道题让我 ...
- vi command
进入vi的命令 vi filename :打开或新建文件,并将光标置于第一行首 vi +n filename :打开文件,并将光标置于第n行首 vi + filename :打开文件,并将光标置于最后 ...
- 79 umount-卸除目前挂在Linux目录中的文件系统
Linux umount命令用于卸除文件系统. umount可卸除目前挂在Linux目录中的文件系统. 语法 umount [-ahnrvV][-t <文件系统类型>][文件系统] 参数: ...
- Angular 2 - 5 分钟快速入门
原文地址: https://angular.io/docs/ts/latest/quickstart.html 让我们从 0 开始创建一个简单的 Angular 2 应用. 下载任何版本的 angul ...
- 高级数组-ArrayList
可以放入任意类型的数据 ArrayList alist=new ArrayList(); alist.Add(440;//装箱,讲int类型的值转换为引用类型 int i1=(int)alist[0] ...