由于工作关系, 客户机器只能通过 linux shell 连接到 mssql 服务器, 自然而然选择了 mssql_cli.
然而在使用的过程中, 通过 sp_helptext 查询存储过程或者函数, 不只是乱七八糟而且会截断, 无论你怎么设置 config 参数都是无效。官方文档的 \sf function 同样存在截断的情况。但是使用本人的方法,可以完美再现脚本。
当然我也有试过以下方法,试图输出完整清晰的脚本,同样失败。
select OBJECT_DEFINITION(object_id(@object_name))
万般无奈之下, 只得自行写了个函数:
- 通过判断 char(13),char(10) 换行回车符
- 将内容分行输出
- 并且每一行如果超过预设长度,则截断在 comma
- 再把输出结果拷贝黏贴至 excel
- 通过 excel 分列,得到完整清晰的 sql 脚本
诚然, comma 判断截断多少有意外,比如 decimal(20,2) 其中的逗号来分行的话,当然是不可接受的,但通过本方法以及少量手动工作,还是尽可能达到目的。脚本如下:
Create function sql_gen (@object_name nvarchar(max), @return_length int)
--@object_name 为对象名,可以是存储过程,函数,视图;@return_length 为 linux shell 下每行输出的字符数量
returns @t table (content nvarchar(max) ,row int,sequence int)
--content 为根据 char(13)+char(10) 分行的内容, row 为标准应该是第几行, sequence 为长度超宽后再次截断的分行序号
as
begin
declare @object_content nvarchar(max)
declare @object_content_pre nvarchar(max)
declare @object_content_pre_reverse nvarchar(max)
declare @object_content_pre_reverse_comma int
declare @object_content_pre1 nvarchar(max)
declare @object_content_pre2 nvarchar(max)
--declare @return_length int=100.00
declare @length int
declare @position int
set @object_content=rtrim((select OBJECT_DEFINITION(object_id(@object_name))))
set @position=charindex(char(13)+char(10),@object_content)
declare @i int=1
declare @j int=1
declare @k int=1
declare @m int=1
set @i=((select len(@object_content)-len(replace(@object_content,char(13)+char(10),'')))/2)
while @j<=@i
begin
set @object_content_pre=(select top 1 left(@object_content,charindex(char(13)+char(10),@object_content)) )
set @object_content=stuff(@object_content,1,charindex(char(13)+char(10),@object_content),'')
set @object_content_pre=replace(replace(@object_content_pre,char(13),''),char(10),'')
set @length=len(@object_content_pre)
set @k=ceiling(@length/@return_length)+1
while @k<>0
begin
set @object_content_pre1=substring(@object_content_pre,1,@return_length)
set @object_content_pre_reverse=REVERSE(@object_content_pre1)
set @object_content_pre_reverse_comma=CHARINDEX(',',@object_content_pre_reverse)
set @object_content_pre1=substring(@object_content_pre,1,@return_length-@object_content_pre_reverse_comma)
set @object_content_pre=substring(@object_content_pre,@return_length+1-@object_content_pre_reverse_comma,len(@object_content_pre))
insert @t(content,row,sequence) select @object_content_pre1,@j,@m
set @length=len(@object_content_pre)
set @k=@k-1
set @m=@m+1
end
set @j=@j+1
set @m=1
end
return
end
执行以下语句可获取脚本,注意 sequence 大于1的值, 代表上一行被截断,少量的手动更新脚本是可能存在的:
select * from sql_gen('对象名称',200) order by row,sequence
刚开始的时候,考虑过使用 存储过程中的 print 输出脚本,免得在 excel 中分列输出,但是,但是,在 mssql_cli 中 print 只能输出一行。