仓酷云

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 870|回复: 8
打印 上一主题 下一主题

[学习教程] MSSQL教程之化解字符串不克不及凌驾8000的办法及交织表...

[复制链接]
飘飘悠悠 该用户已被删除
跳转到指定楼层
楼主
发表于 2015-1-16 22:28:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
你看出了作者的深度?深处半米!当初是冲那么多的大牛给他写序才买的,后来才发现无啥内容,作者也只是才用几年的新手,百花了几十两银子,再次感叹当今社会的虚伪与浮躁字符串
常常有人提到,用静态天生SQL语句的办法处置数据时,处置语句超长,没法处置的成绩
上面就会商这个成绩:

/*--数据测试情况--*/
ifexists(select*fromdbo.sysobjectswhereid=object_id(N[tb])andOBJECTPROPERTY(id,NIsUserTable)=1)
droptable[tb]
GO

createtabletb(单元称号varchar(10),日期datetime,发卖额int)
insertintotb
selectA单元,2001-01-01,100
unionallselectB单元,2001-01-02,101
unionallselectC单元,2001-01-03,102
unionallselectD单元,2001-01-04,103
unionallselectE单元,2001-01-05,104
unionallselectF单元,2001-01-06,105
unionallselectG单元,2001-01-07,106
unionallselectH单元,2001-01-08,107
unionallselectI单元,2001-01-09,108
unionallselectJ单元,2001-01-11,109

/*--请求了局
日期A单元B单元C单元D单元E单元F单元G单元H单元I单元J单元
----------------------------------------------------------
2001-01-01100000000000
2001-01-02010100000000
2001-01-03001020000000
2001-01-04000103000000
2001-01-05000010400000
2001-01-06000001050000
2001-01-07000000106000
2001-01-08000000010700
2001-01-09000000001080
2001-01-11000000000109
--*/

/*--惯例处置办法
declare@sqlvarchar(8000)
set@sql=select日期=convert(varchar(10),日期,120)
select@sql=@sql+,[+单元称号
+]=sum(case单元称号when+单元称号+then发卖额else0end)
from(selectdistinct单元称号fromtb)a
exec(@sql+fromtbgroupbyconvert(varchar(10),日期,120))
--*/

/*--成绩--*/

假如单元良多,这时候,@SQL的值就会被截断,从而堕落.

上面给出三种办理举措:

--/*--办法1.多个变量处置

--界说变量,估量必要几个变量才干保留完一切数据
declare@sql0varchar(8000),@sql1varchar(8000)
--,...@sqlnvarchar(8000)

--天生数据处置一时表
selectid=identity(int,0,1),groupid=0
,值=,[+单元称号+]=sum(case单元称号when
+单元称号+then发卖额else0end)
into#tempfrom(selectdistinct单元称号fromtb)a

--分组一时表,判别慨最多几个单元能够组分解一个不凌驾8000的字符串,这里取假定为5个
update#tempsetgroupid=id/5--5为每组的单元个数

--天生SQL语句处置字符串
--初始化
select@sql0=
,@sql1=
--...
--,@sqln

--失掉处置字符串
select@sql0=@sql0+值from#tempwheregroupid=0--第一个变量
select@sql1=@sql1+值from#tempwheregroupid=1--第二个变量
--select@sqln=@sqln+值from#tempwheregroupid=n--第n个变量

--查询
exec(select日期=convert(varchar(10),日期,120)
+@sql0+@sql1
--...+@sqln
+fromtbgroupbyconvert(varchar(10),日期,120)
)

--删除一时表
droptable#temp

/*
长处:对照天真,数据量年夜时只必要增添变量就好了.不必修改其他部分
弱点:要自行估量处置的数据,估量不敷就会堕落
*/
--*/


--/*--办法2.bcp+isql

--由于要用到bcp+isql,以是必要这些信息
declare@servernamevarchar(250),@usernamevarchar(250),@pwdvarchar(250)
select@servername=zj--服务器名
,@username=--用户名
,@pwd=--暗码

declare@tbnamevarchar(50),@sqlvarchar(8000)

--创立数据处置一时表
set@tbname=[##temp_+convert(varchar(40),newid())+]
set@sql=createtable+@tbname+(值varchar(8000))
insertinto+@tbname+values(createview
+stuff(@tbname,2,2,)+as
select日期=convert(varchar(10),日期,120))
exec(@sql)

set@sql=insertinto+@tbname+
select,[+单元称号+]=sum(case单元称号when
+单元称号+then发卖额else0end)
from(selectdistinct单元称号fromtb)a
exec(@sql)

set@sql=insertinto+@tbname+
values(fromtbgroupbyconvert(varchar(10),日期,120))
exec(@sql)

--天生创立视图的文件,注重利用了文件:c:        emp.txt
set@sql=bcp"+@tbname+"out"c:        emp.txt"/S"
+@servername+"/U"+@username+"/P"+@pwd+"/c
execmaster..xp_cmdshell@sql

--删除一时表
set@sql=droptable+@tbname
exec(@sql)

--挪用isql天生数据处置视图
set@tbname=stuff(@tbname,2,2,)
set@sql=isql/S"+@servername
+case@usernamewhenthen"/Eelse"/U"+@username+"/P"+@pwd+"end
+/d"+db_name()+"/i"c:        emp.txt"

execmaster..xp_cmdshell@sql

--挪用视图,显现处置了局
set@sql=select*from+@tbname+
dropview+@tbname
exec(@sql)

/*
长处:程序主动处置,不存在判别毛病的成绩
弱点:庞大,经由的步骤多,简单堕落,并且必要必定的操纵员权限
*/
--*/


--/*--办法3.多个变量处置,综合了办法1及办法2的长处,办理了办法1中必要工资判别的成绩,主动依据要处置的数据量举行变量界说,同时又制止了办法2的烦琐

declare@sqlheadvarchar(8000),@sqlendvarchar(8000)
,@sql1varchar(8000),@sql2varchar(8000),@sql3varchar(8000),@sql4varchar(8000)
,@iint,@icvarchar(20)

--天生数据处置一时表
selectid=identity(int,0,1),gid=0
,a=,[+单元称号+]=sum(case单元称号when
+单元称号+then发卖额else0end)
into#from(selectdistinct单元称号fromtb)a

--判别必要几个变量来处置
select@i=max(len(a))from#
print@i
set@i=7800/@i

--分组一时表
update#setgid=id/@i
select@i=max(gid)from#

--天生数据处置语句
select@sqlhead=select日期=convert(varchar(10),日期,120)
,@sqlend=fromtbgroupbyconvert(varchar(10),日期,120)
,@sql1=,@sql2=select,@sql3=,@sql4=

while@i>=0
select@ic=cast(@iasvarchar),@i=@i-1
,@sql1=@+@ic+varchar(8000),+@sql1
,@sql2=@sql2+@+@ic+=,
,@sql3=select@+@ic+=@+@ic++afrom#wheregid=+@ic
+char(13)+@sql3
,@sql4=@sql4+,@+@ic

select@sql1=declare+left(@sql1,len(@sql1)-1)+char(13)
,@sql2=left(@sql2,len(@sql2)-1)+char(13)
,@sql3=left(@sql3,len(@sql3)-1)
,@sql4=substring(@sql4,2,8000)

--实行
exec(@sql1+@sql2+@sql3+
exec(+@sqlhead+++@sql4+++@sqlend+)
)

--删除一时表
droptable#
--*/


办法3中,关头要做修正的是上面两句,其他基础上不必做改动:

--天生数据处置一时表,修正a=前面的内容为响应的处置语句
selectid=identity(int,0,1),gid=0
,a=,[+code+]=sum(caseb.c_codewhen
+code+thenb.valueelse0end)
into#from#Class

--天生数据处置语句,将@sqlhead,@sqlend赋值为响应的处置语句头和尾
select@sqlhead=selecta.id,a.name,a.code
,@sqlend=from#Departa,#Valuebwherea.Code=b.d_Codegroupbya.id,a.code,a.name
,@sql1=,@sql2=select,@sql3=,@sql4=




Archive非常适合存储大量的独立的,作为历史记录的数据。因为它们不经常被读取。Archive拥有高效的插入速度,但其对查询的支持相对较差
简单生活 该用户已被删除
沙发
发表于 2015-1-19 14:04:03 | 只看该作者
这一点很好的加强了profiler的功能。但是提到profiler提醒大家注意一点。windows2003要安装sp1补丁才能启动profiler。否则点击没有反应。
再现理想 该用户已被删除
板凳
发表于 2015-1-26 10:05:18 | 只看该作者
很多书籍啊,不过个人认为看书太慢,还不如自己学。多做实际的东西,就会遇到很多问题,网上搜下解决问题。不断重复这个过程,在配合sql的F1功能。
精灵巫婆 该用户已被删除
地板
发表于 2015-2-4 14:22:43 | 只看该作者
学习SQL语言的话如果要学会去做网站就不是很难!但是要做数据库管理的话就有难度了!
飘飘悠悠 该用户已被删除
5#
 楼主| 发表于 2015-2-10 01:59:30 | 只看该作者
你可以简单地认为适合的就是好,不适合就是不好。
活着的死人 该用户已被删除
6#
发表于 2015-2-28 15:11:52 | 只看该作者
如果我们从集合论(关系代数)的角度来看,一张数据库的表就是一组数据元的关系,而每个SQL语句会改变一种或数种关系,从而产生出新的数据元的关系(即产生新的表)。
小妖女 该用户已被删除
7#
发表于 2015-3-10 00:46:01 | 只看该作者
但是随着数据量的增大,这种成本差距会逐渐减小,趋于相等。(500万数量级只相差10%左右)
老尸 该用户已被删除
8#
发表于 2015-3-17 03:33:46 | 只看该作者
而写到本地,我又考虑到效率问题.大家来讨论讨论吧,分数不打紧,就给10分,十全十美,没啥对错,各抒己见,但是要有说服力的哦~
透明 该用户已被删除
9#
发表于 2015-3-23 18:13:28 | 只看该作者
这是一个不错的新特性。虽然索引的附加字段没有索引键值效率高,但是相对映射到数据表中效率还是提高了很多。我做过试验,在我的实验环境中会比映射到表中提高30%左右的效率。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|仓酷云 鄂ICP备14007578号-2

GMT+8, 2024-12-23 00:41

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表