【网学网提醒】:网学会员,鉴于大家对SQL数据库资料整理2006(CSDN精装版)十分关注,会员在此为大家搜集整理了“SQL数据库资料整理2006(CSDN精装版)”一文,供大家参考学习!
发表地址:bbs.54master/viewthread.php?action=printable&;tid=127814
前言:最近比较忙,一直没时间整理自己的帖子和文件,这里整理的,主要是一些工作中前言碰到、朋友问到的已经解决了的资料;代码的例子多,说明的文字部分少点!,^-^,文采不好,就是有点懒,大多代码;有些资料可能会重复、存在在错误,希望大家能提出与谅解。作者:DVD/OK_008整理时间整理时间:2006-12联系方式联系方式:glal@163作者myblog:wghaoblogs/
SQL游标学习
游标一般格式:游标一般格式:
DECLARE游标名称CURSORFORSELECT字段1,字段2,字段3,...FROM表名WHERE...OPEN游标名称FETCHNEXTFROM游标名称INTO变量名1,变量名2,变量名3,...WHILE@@FETCH_STATUS=0BEGINSQL语句执行过程......FETCHNEXTFROM游标名称INTO变量名1,变量名2,变量名3,...ENDCLOSE游标名称DEALLOCATE游标名称
例子:例子:
/*功能:数据库表格tbl_users数据deptiduseridusername112100101102abc
要求用一个sql语句输出下面结果deptidusername
1ab2c[要求用游标实现]设计:OK_008时间:2006-05备注:无*/
createtable#Temp1(deptidint,useridint,usernamevarchar(20))--待测试的数据表createtable#Temp2(deptidint,usernamevarchar(20))--结果表
--先把一些待测试的数据插入到待测试表#Temp1中insertinto#Temp1select1,100,'a'unionallselect1,101,'b'unionallselect1,131,'d'unionallselect1,201,'f'unionallselect2,302,'c'unionallselect2,202,'a'unionallselect2,221,'e'unionallselect3,102,'y'unionallselect3,302,'e'unionallselect3,121,'t'-declare@deptidint,@usernamevarchar(20)--定义游标declareSelect_cursorcursorforselectdeptid,usernamefrom#Temp1openSelect_cursorfetchnextfromSelect_cursorinto@deptid,@usernamewhile@@fetch_status=0/*@@FETCH_STATUS=0FETCH语句成功@@FETCH_STATUS=-1FETCH语句失败或此行不在结果集中@@FETCH_STATUS=-2被提取的行不存在*/begin--当表#Temp2列deptid存在相同的数据时,就直接在列username上追加@username值if(exists(select*from#Temp2wheredeptid=@deptid))update#Temp2setusername=username+@usernamewheredeptid=@deptidelse--插入新数据insertinto#Temp2select@deptid,@usernamefetchnextfromSelect_cursorinto@deptid,@usernameendcloseSelect_cursordeallocateSelect_cursorselect*from#Temp2--测试结果Droptable#Temp1,#Temp2--提取操作的列数据放到局部变量中--返回被FETCH语句执行的最后游标的状态
自动生成表的更新数据的存储过程
设计原因:在数据库设计中,有时候建立了很多表,每个表都有Insert、Update、Delete
结构基本相同的存储,要是能有个自动生成表的更新数据的存储过程,就方便了我们不必浪
费时间
去写每一张表的Insert、Update、Delete存储过程。
设计方法设计方法:先提取表的各字段信息,包含字段的数据类型、数据定义长度、是否主键
等。再根据提取出来的信息构造成表的更新数据的存储过程。下面的方法是有一个用户自定义函数FN_GetObjColInfo和一个存储过程SP_CreateProcdure来实现。。用户自定义函数FN_GetObjColInfo::
/*功能:返回某一表的所有字段、存储过程、函数的参数信息设计:OK_008时间:2006-05*/CREATEFUNCTIONFN_GetObjColInfo(@ObjNamevarchar(50))RETURNS@Return_TableTABLE(TNamenvarchar(50),TypeNamenvarchar(50),TypeLengthnvarchar(50),Colstat)ASBEGININSERT@Return_Table/*主要是从系统表中提取表(对象)的各字段信息。sysobjects:在数据库内创建的每个对象(约束、默认值、日志、规则、存储过程等)在表中占一行syscolumns:每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行systypes:保存数据类型和用户定义数据类型*/selectb.nameas字段名,c.nameas字段类型,b.length/2as字段长度,b.colstatas是否自动增长fromsysobjectsainnerjoinsyscolumnsbona.id=b.idinnerjoinsystypesconc.xusertype=b.xtypewherea.name=@ObjNameorderbyB.ColIDRETURNENDGOBit
存储过程SP_CreateProcdure::
CREATEPROCEDURESP_CreateProcdure@TableNamenvarchar(50)AS/*功能:自动生成表的更新数据的存储过程如:当建立表MyTable后,执行SP_CreateProcdure,生成表MyTable的数据更新的存储过程UP_MyTable设计:OK_008时间:2006-05备注:1、请在查询分析器上执行:EXECSP_CreateProcdureTableName2、由于生成的字符串长度合计很多时候存在>4000以上,所有只使用Print输出,再Copy即可。3、该方法能生成一般表的更新数据的存储过程,其中更新格式可以根据实际情况修改。设计方法:1、提取表的各个字段信息2、──┰─构造更新数据过程├─构造存储过程参数部分├─构造新增数据部分├─构造更新数据部分├─构造删除数据部分3、分段PRINT4、把输出来的结果复制到新建立存储过程界面中即可使用。*/DECLARE@strParameternvarchar(3000)DECLARE@strInsertnvarchar(3000)DECLARE@strUpdatenvarchar(3000)DECLARE@strDeletenvarchar(500)DECLARE@strWhereDECLARE@strNewIDnvarchar(100)nvarchar(100)
DECLARE@SQL_CreateProcnvarchar(4000)
SET@SQL_CreateProc='CREATEPROCEDUREUP_'+@TableName+char(13)+'@INTUpdateIDint,'+'/*-1删除0修改1新增*/'
SET@strParameter=''SET@strInsert=''SET@strUpdate=''SET@strWhere=''
DECLARE@TNamenvarchar(50),@TypeNamenvarchar(50),@TypeLengthnvarchar(50),@ColstatbitDECLAREObj_CursorCURSORFORSELECT*FROMOPENObj_CursorFN_GetObjColInfo(@TableName)
FETCHNEXTFROMObj_Curso
rINTO@TName,@TypeName,@TypeLength,@ColstatWHILE@@FETCH_STATUS=0BEGIN--构造存储过程参数部分SET@strParameter=@strParameter+CHAR(13)+'@'+@TName+''+@TypeName+(CASEWHEN@TypeName='nvarchar'THEN'('+@TypeLength+')'ELSE''END)+','--构造新增数据部分IF@Colstat=0SET@strInsert=@strInsert+'@'+@TName--构造更新数据部分IF(@strWhere='')BEGINIF@Colstat=0SET@strNewID='SET@'+@TName+'=(SelectISNULL(MAX('+@TName+'),0)From'+@TableName+')+1--取新的ID'SET@strWhere='WHERE'+@TName+'='+'@'+@TNameENDELSESET@strUpdate=@strUpdate+@TName+'='+'@'+@TName+','--构造删除数据部分FETCHNEXTFROMObj_CursorINTO@TName,@TypeName,@TypeLength,@ColstatENDCLOSEObj_CursorDEALLOCATEObj_Cursor+','
SET@strParameter=LEFT(@strParameter,LEN(@strParameter)-1)--去掉最右边的逗号SET@strUpdate=LEFT(@strUpdate,LEN(@strUpdate)-1)SET@strInsert=LEFT(@strInsert,LEN(@strInsert)-1)
--存储过程名、参数PRINT@SQL_CreateProc+@strParameter+CHAR(13)+'AS'--修改PRINT'IF(@INTUpdateID=0)'PRINT'BEGIN'+CHAR(13)
PRINTCHAR(9)+'UPDATE'+@TableName+'SET'+@strUpdate+CHAR(13)+CHAR(9)+@strWherePRINT'END'--增加PRINT'ELSEIF(@INTUpdateID=1)'PRINT'BEGIN'
PRINTCHAR(9)+@strNewIDPRINTCHAR(9)+'INSERTINTO'+@TableName+'('+REPLACE(@strInsert,'@','')+')VALUES
('+@strInsert+')'PRINT'END'
--删除PRINT'ELSE'PRINT'BEGIN'PRINTCHAR(9)+'DELETEFROM'+@TableName+@strWherePRINT'END'PRINT'GO'GO
绘画日历
设计原因:设计原因:记得那时,周末没事干随便想到的,只是为了学习。设计方法:设计方法:先构造一个月的日历图,再使用循环绘画1-12月的日历图。
/*功能:绘画日历设计:OK_008时间:2006-05*/DECLARE@Yearnvarchar(4)DECLARE@YearMonthnvarchar(7)DECLARE@strTopnvarchar(200)DECLARE@ForIINT,@ForYearINT,@MaxDayINTDECLARE@RowXINT--行位置DECLARE@strWeekDayListnvarchar(20)DECLARE@strPrintnvarchar(300)--月份
--======================================SET@Year='2006'--请在这里输入年份
--======================================--设置日历上边的标题格式SET@strTop='日'+char(9)+'一'+char(9)+'二'+char(9)+'三'++char(9)+'四'++char(9)+'五'++char(9)+'六'+char(13)+'───────────────────────────'--设置星期列表SET@strWeekDayList='日一二三四五六'SET@ForYear=1WHILE@ForYear<=12BEGIN--取当月格式SET@YearMonth=@Year+'-'+CAST(@ForYearASnvarchar(2))--取当月的最大日期SET@MaxDay=DAY(DATEADD(Day,-1,DATEADD(Month,1,@YearMonth+'-01')))--找出1号的开始位置SET@RowX=CHARINDEX(RIGHT(DATENAME(WeekDay,@YearMonth+'-01'),1),@strWeekDayList)-1--1月份至12月份
SET@strPrint=''SET@ForI=1WHILE@ForI<=@RowX--构造1号的位置,并绘画空白处BEGINSET@strPrint=@strPrint+CHAR(9)SET@ForI=@ForI+1ENDSET@ForI=1WHILE@ForI<=@MaxDay
--构造2号到月底的位置,并绘画BEGINSET@strPrint=@strPrint+CAST(@ForIASnvarchar(2))+Char(9)SET@RowX=@RowX+1SET@ForI=@ForI+1IF(@RowX%7=0)--满一个星期就换行BEGINSET@RowX=0SET@strPrint=@strPrint+CHAR(13)ENDENDSET@ForYear=@ForYear+1--打印输出一个月的结果PRINT'━━━━━━━━━━━━━━━━━━━━━━━━━━━'PRINT+Char(9)++Char(9)+'PRINT@strTopPRINT@strPrint+CHAR(10)END执行结果:执行结果:
━━━━━━━━━━━━━━━━━━━━━━━━━━━2006-1日一二三四五六
'+@YearMonth+CHAR(10)
───────────────────────────18152229291623303101724314111825512192661320277142128
━━━━━━━━━━━━━━━━━━━━━━━━━━━2006-2日一二三四五六
───────────────────────────15121961320714218152229162331017244111825
26
27
28
━━━━━━━━━━━━━━━━━━━━━━━━━━━2006-3日一二三四五六
───────────────────────────15121926613202771421288152229291623303101724314111825
。。。。。。
一个金额转化的问题
设计原因:记得是有一客户的特别要求,开始有点晕,后来还是能做好。设计原因:记得是有一客户的特别要求,开始有点晕,后来还是能做好。
/*功能:把Money类型转换成nvarchar类型,保留三位小数,而且把数值后面多余的0去掉。如money类型的数值2.59100,转化成nvarchar(20)类型时,要求的结果是2.591如money类型的数值89.7800,转化成nvarchar(20)类型时,要求的结果是89.78设计:OK_008时间:2006-07*/CREATETABLE#Temp([ID]int,F1nvarchar(20),F2nvarchar(20),SMoneymoney,Dmoneymoney)INSERTINTO#TempSELECT1,'F1','F2',45.895,23.89000UNIONSELECT2,'F2','F3',45.895,234.67UNIONSELECT3,'F3','F4',25.835,32.123UNIONSELECT4,'F4','F5',13.7600,31.6754UNIONSELECT5,'F5','F6',34.783,78.345/*要求的结果如下:SMoney+'X'+Dmoney-----------------------------------------------------45.895X23.8945.895X234.6725.835X32.12313.76X31.67534.783X78.345*/SELECT*,cast(SMoneyasnvarchar(20))FROM/*经过3次的数据才可以把money类型的数据后边多余的零给去掉,money先转换成decimal,再转换成float,然后是nvarchar#Temp
*/SELECTCAST(CAST(CAST(SmoneyASdecimal(20,3))ASfloat)asnvarchar)+'X'+CAST(CAST(CAST(DmoneyASdecimal(20,3))ASfloat)ASnvarchar)FROM#Temp
DROPTABLE#Temp
多个变量赋值问题.sql多个变量赋值问题.sql
设计原因:上有一朋友问到这个问题,感觉顶有意思的,顺便拿过来。设计原因:记得在itpub上有一
朋友问到这个问题,感觉顶有意思的,顺便拿过来。
/*=================================原来的问题是这样的:=================================现在的表结构是这样的IDReferIDReferCount10221NULL32NULL431然后声明四个变量declare@t1intdeclare@t2intdeclare@t3intdeclare@t4int然后使用四条记录中的ReferCount为值四个变量赋值问题是能不能使用一条sql语句完成,用case行不行的请高手们指教*/--解决方法:
CREATETABLE#Temp(IDint,ReferIDint,ReferCountint)INSERTINTO#TempSELECT1,0,2UNIONALLSELECT2,1,NULLUNIONALLSELECT3,2,NULLUNIONALLSELECT4,3,1DECLARE@t1intDECLARE@t2intDECLARE@t3intDECLARE@t4int--根据ID的唯一性来查询
SELECT@t1=CASEIDWHEN1THENReferCountELSE@t1END,@t2=CASEIDWHEN2THENReferCountELSE@t2END,@t3=CASEIDWHEN3THENReferCountELSE@t3END,@t4=CASEIDWHEN4THENReferCountELSE@t4ENDFROM#TempSELECT@t1AS'@t1',@t2AS'@t2',@t3AS'@t3',@t4AS'@t4'DROPTABLE#Temp/*运行结果:@t1|@t2|@t3|@t4-------------------2*/|NULL|1|NULL
计算在一段时间内某周几(如星期一)计算在一段时间内某周几(如星期一)的所有日期一段时间内某周几
设计方法:设计方法:先提取第1个星期一,然后就是循环+7。难点就是怎么样提取第1个星期一。
/*功能:计算在某一段时间内某周几(如星期一)的所有日期设计:OK_008时间:2006-10*/DECLARE@DatedatetimeDECLARE@StartDatedatetimeDECLARE@EndDatedatetimeDECLARE@WeekDayintDECLARE@iint
SETDATEFIRST7SET@StartDate='2006-01-01'SET@EndDate='2006-12-31'SET@WeekDay=2
--设置每周的第一天--统计的开始日期--统计的结束日期--根据实际的@@DATEFIRST而定,一般默认是7,如
@StartDate='2006-01-01'时候,@WeekDay=3表示星期二SET@i=DATEPART(weekday,@StartDate)PRINT'每周的第1天设置@@DATEFIRST:'+CAST(@@DATEFIRSTASnvarchar(1))PRINT'开始日期对应一周的第几天:IF(@i<=@WeekDayAND@i<7)SET@i=@WeekDay-@iELSEIF(@i<=@WeekDayAND@i=7)SET@i=@i-@WeekDayELSESET@i=@@DATEFIRST-@i+@WeekDay'+CAST(@iASnvarchar(1))
SET@Date=DATEADD(day,@i,@StartDate)WHILE@Date<=@EndDateBEGINIF(@StartDate<=@Date)PRINTCONVERT(nvarchar(10),@Date,121)SET@Date=DATEADD(Week,1,@Date)ENDGO
/*==============运行结果================*//*每周的第1天设置@@DATEFIRST:7开始日期对应一周的第几天:2006-01-022006-01-09......2006-12-182006-12-25*/1
字符串的分割
/*功能:实现字符串的分割,达到批量提交数据参数和分批处理功能。设计:wgh时间:2006-09*/declare@str1nvarchar(100)--要分割的字符串declare@str2nvarchar(100)--分割得的子字符串declare@splitnvarchar(40)--分割字符or字符串declare@patIndexintset@split='★■->'set@str1='334,345,''
dfd'',★■->select*fromEmployee★■->45654DFG★■->452897★■->97887657★■->123445'set@str2=''--从左至右分割whilebeginset@patIndex=patindex('%'+@split+'%',@str1)--patindex函数返回@str1中@split第一次出现的起始位置if@patIndex>0set@str2=left(@str1,@patIndex-1)--截取@str1中以@split为分割的左边的字符串elseset@str2=@str1print@str2--调试@str1<>@str2--分割字符or字符串第一次出现的起始位置
/*执行过程....*/if@patIndex>0set@str1=right(@str1,len(@str1)-len(@str2)-len(@split))--截断字符串,为的是下一次循环能取得,@str1中@split第一次出现的起始位置end
查找某一数据库没有主鍵的所有用户表
/*功能:查找所有(某一)数据库没有主鍵的所有用户表设计:wgh时间:2006-06*/
/*设计方法:使用游标的方法,从系统表sysobjects、syscolumns、sysindexes提取表的相关信息。*/DECLARE@DatabaseNamenvarchar(20)DECLARE@Execute_Sqlnvarchar(4000)SET@DatabaseName='ydhr'--要是要检查所有数据库就SET@DatabaseName=''CREATEtable#Temp(DatabaseNamenvarchar(20),TableNamenvarchar(50))IFISNULL(@DatabaseName,'')=''DECLAREcursor_SqlCURSORFORSELECTnameFROMmaster..sysdatabasesWHEREdbid>=7--dbid>=7都是属于用户建立的数据库ELSEDECLAREcursor_SqlCURSORFORSELECTnameFROMmaster..sysdatabasesWHEREdbid>=7ANDname=@DatabaseNameOPENcursor_SqlFETCHNEXTFROMcursor_SqlINTO@DatabaseNameWHILE@@FETCH_STATUS=0BEGINSET@Execute_Sql='INSERTINTO#TempSELECT'''+@DatabaseName+''',A.nameFROM'+@DatabaseName+'..sysobjectsASAWHEREOBJECTPROPERTY(A.id,N''IsUserTable'')=1ANDNOTEXISTS(SELECT1FROM'+@DatabaseName+'..sysindexesASiINNERJOIN
'+@DatabaseName+'..sysindexkeyskONi.id=k.idANDi.indid=k.indidINNERJOIN'+@DatabaseName+'..sysobjectsASoONi.id=o.idINNERJOIN'+@DatabaseName+'..syscolumnsconi.id=c.idandk.colid=c.colid
WHEREo.xtype=''U''ANDA.id=i.idANDEXISTS(SELECT1FROM'+@DatabaseName+'..sysobjectsWHERExtype=''PK''ANDname=i.name))'/*OBJECTPROPERTY()返回当前数据库中对象的有关信息,OBJECTPROPERTY(对象id,N''IsUserTable'')表示是否为用户表xtype='U'在系统表sysobjects中表示查询的对象属于用户表,与OBJECTPROPERTY(对象id,N''IsUserTable'')功能一致,只是用法格式不同xtype='PK'PRIMARYKEY约束(类型是K)*/EXECUTE(@Execute_Sql)PRINT@Execute_Sql--为了能更清楚语句的含义,我这里可以使用PRINT查看整条执行语句
FETCHNEXTFROMcursor_SqlINTO@DatabaseNameENDCLOSEcursor_SqlDEALLOCATEcursor_SqlSELECT*FROM#TempDROPTABLE#Temp
重命名数据库、重命名数据库、表、列
重命名数据库、表、列名,使用系统存储过程sp_rename是最简单的了。我们先来看看帮助文档的说明:
sp_rename
更改当前数据库中用户创
建对象(如表、列或用户定义数据类型)的名称。语法sp_rename[@objname=]'object_name',[@newname=]'new_name'[,[@objtype=]'object_type']@objname对象名@objtype对象类型值COLUMNDATABASEINDEXOBJECT要重命名的列。用户定义的数据库。要重命名数据库时需用此选项。用户定义的索引。在sysobjects中跟踪的类型的项目。例如,OBJECT可用来重命名约束(CHECK、FOREIGNKEY、PRIMARY/UNIQUEKEY)、用户表、视图、存储过程、触发器和规则等对象。描述
USERDATATYPE
通过执行sp_addtype而添加的用户定义数据类型。
/*功能:重命名数据库、表、列编写:wgh时间:2006-11*/
--重新命名数据库IFEXISTS(SELECT1FROMmaster..sysdatabasesWHEREname='BBS')EXECUTEsp_rename@objname='BBS',@newname='BBS1',@objtype='DATABASE'
--重新命名表名IFEXISTS(SELECT1FROMsysobjectsWHEREname='bbs_log'AND
OBJECTPROPERTY(id,'IsUserTable')=1)EXECUTEsp_rename@objname='bbs_log',@newname='bbs_log1',@objtype='OBJECT'
--重新命名列名IFEXISTS(SELECT1FROMsyscolumnsWHEREid=OBJECT_ID('bbs_log')ANDname='ColumnName'ANDOBJECTPROPERTY(id,'IsUserTable')=1)EXECUTE@objname='bbs_log.[ColumnName]',@newname='NewColumnName',@objtype='COLUMN'sp_rename
格式化字符串,如输入01自动生成0000001
/*===================================================功能:格式化字符串,如输入01自动生成0000001备注:当位数达到10以上,要另写算法,否则出错设计:weiguohao日期:2006-03-11===================================================*/CREATEFUNCTIONFORMAT_STR(@strXNvarchar(20),@FormatLengthINT)RETURNSNVARCHAR(20)ASBEGINDECLARE@ReturnNVARCHAR(20)DECLARE@LengthINTSET@Length=LEN(@strX)IF@Length>=@FormatLengthSET@Return=@strXELSEBEGIN
--格式化,只要是调用到数学函数POWER,其他就不再说明,太简单了SET@Return=CAST(RIGHT(POWER(10,@FormatLength),@FormatLength-@Length)AS
NVARCHAR(20))+@strXENDRETURN@ReturnEND
一个厂家与销售商的查询问题
论坛上的一位朋友,如下:问题来来自itpub论坛上的一位朋友,如下:多个厂家多个销售商每个厂家对任一销售商都免费前10次的货款有厂家表,销售表,销售商表想求得销售商三个表拼合一起的视图视图中有个字段标出免费的销售记录?
厂家表:ID,名称销售表:ID,销售单号厂家:ID,销售商ID销售商:ID,销售商名称预得视图:销售单ID,厂家ID,销售商ID,是否免费谢谢哥哥姐姐了。帮忙写写……
解答:解答:
CREATETABLE#Suppliers(SupplierIDint,CompanyNamenvarchar(40))--厂家表CREATETABLE#Sell(SellIDint,SupplierIDint,CustomerIDint)--销售表CREATETABLE#Customers(CustomerIDint,CompanyNamenvarchar(40))--销售商、客户表INSERTINTO#SuppliersSELECT1,N'Supplier1'UNIONALL
SELECT2,N'Supplier2'INSERTINTO#CustomersSELECT1,N'Customer1'UNIONALLSELECT2,N'Customer2'INSERTINTO#SellSELECT1,1,1UNIONALLSELECT2,1,1UNIONALLSELECT3,1,1UNIONALLSELECT4,1,1UNIONALL
SELECT5,1,1UNIONALLSELECT6,1,1UNIONALLSELECT7,1,1UNIONALLSELECT8,1,2UNIONALLSELECT9,1,2UNIONALLSELECT10,1,2UNIONALLSELECT11,1,2UNIONALLSELECT12,1,2UNIONALLSELECT13,1,2UNIONALLSELECT14,1,2UNIONALLSELECT15,2,1UNIONALLSELECT16,2,1UNIONALLSELECT17,2,2UNIONALLSELECT18,2,2UNIONALLSELECT18,2,2--每个厂家对任一销售商都免费前3次的货款(根据实际修改提前多少次是免费的货款)--主要是使用到一个GROUPBY...HAVING...在对数据进行分组和聚合后,就会用到HAVING子句中的条件SELECTA.*,(CASEWHENEXISTS(SELECT1FROM#SellASBWHERE
A.SupplierID=B.SupplierIDANDA.CustomerID=B.CustomerIDANDB.SellID<=A.SellIDGROUPBYB.CustomerIDHAVINGCOUNT(1)<=3)THEN'是'ELSE'否'END)AS'是否免费'FROM#SellASADROPTABLE#Suppliers,#Sell,#Customers[CODE]结果------------------------------------/*SellIDSupplierIDCustomerID是否免费-----------------------------------------111是211是311是411否511否611否711否812是912是1012是1112否1212否1312否1412否1521是
1621是1722是1822是1822是*/[/CODE]
不用游标就可以实现的一个问题
原来问题如下:原来问题如下:
如果有2个表T1(aid,bid),T2(bid,bname,bprice)T1的字段表示顾客ID和商品ID,一个顾客可以买多种商品现在T1有记录:1,101,111,122,102,13T2的字段表示商品ID,商品名称,商品价格现在T2有记录:10,aaa,111,bbb,212,ccc,313,ddd,4现在要实现显示顾客买的商品名称和价钱即字段:aid,bname,bprice但是同一个顾客只保留一个ID,其他为null请问怎么实现?即将上面的记录实现为:1,aaa,1,bbb,2,ccc,32,aaa,1,ddd,4如果不用游标有办法实现吗?解决方法:解决方法:
CREATETABLE#T1(aidint,bidint)INSERTINTO#T1SELECT1,10UNIONALLSELECT1,11UNIONALLSELECT1,12UNIONALLSELECT2,10UNIONALLSELECT2,13CREATETABLE#T2(bidint,bnamenvarchar(10),bpriceint)INSERTINTO#T2SELECT10,'aaa',1UNIONALLSELECT11,'bbb',2UNIONALLSELECT12,'ccc',3UNIONALLSELECT13,'ddd',4SELECTA.aid,B.bname,B.bpriceINTO#T3FROM#T1ASALEFTOUTERJOIN#T2ASBONA.bid=B.bidDECLARE@aidint,@lastaidintUPDATE#T3SET@aid=(CASEWHENISNULL(@lastaid,'')=aidTHENNULLELSEaidEND),aid=@aid,@lastaid=aidSELECT*FROM#T3DROPTABLE#T1,#T2,#T3结果:结果:/*1aaa1NULLbbb2NULLccc32aaa1NULLddd4*/
一个数据替换问题
原来的问题:原来的问题:我要將([4000]+[3900])/([3100]+[3200]+[3900])*[3900]替换成(0+0)/(0+0+0)*0就是把[4000]樣的替換成0解决方法如下,解决方法如
下,
建立一个自定义函数:CREATEFUNCTIONCreateMathExpression(@ColumnNamenvarchar(500))RETURNSnvarchar(1000)ASBEGINDECLARE@FieldValuenvarchar(20)DECLARE@Returnnvarchar(1000)DECLARE@Sqlnvarchar(1000)DECLARE@IndexintDECLARE@EndbitSET@End=0SET@Return=''--SET@ColumnName='[3900]/222.8*([3200]/[3900])'SET@Index=CHARINDEX('[',@ColumnName)WHILE@Index<>0BEGINIF@End=0BEGINSET@Index=CHARINDEX('[',@ColumnName)IF@Index=0GOTOExit_WhileSET@Return=@Return+LEFT(@ColumnName,@Index-1)SET@End=1ENDELSEBEGINSET@Index=CHARINDEX(']',@ColumnName)SET@FieldValue=LEFT(@ColumnName,@Index-1)
SET@Return=@Return+'0'SET@End=0ENDSET@ColumnName=RIGHT(@ColumnName,len(@ColumnName)-@Index)ENDExit_While:SET@Return=@Return+@ColumnNameRETURN@ReturnEND-------------------------------------------------------------------例子:DECLARE@Nnvarchar(200)SET@N='([4000]+[3900])/([3100]+[3200]+[3900])*[3900]'SELECT@NSELECTdbo.CreateMathExpression(@N)
------------------------结果:(0+0)/(0+0+0)*0备注:可以忽略。备注:函数中的一些代码是别的用途,可以忽略。
向表中一列插入1-100的连续数
上看到一朋友问到这样的一个问题:在BBS上看到一朋友问到这样的一个问题:求助:求助:向表中一列插入1-100的连续数字段(),怎么连续给tableA中有BH字段(INT),怎么连续给BH赋值1-100,象下面的一样BH-----------------------------------------------12...100根据常规的方法,来实现以上的功能。一朋友所写的这样:根据常规的方法,我们会想到使用While来实现以上的功能。如,一朋友所写的这样:CREATETABLETestTable(BHINT)GOSETNOCOUNTONGODECLARE@MyCounterINT
SET@MyCounter=1WHILE(@MyCounter<101)BEGININSERTINTOTestTableVALUES
(@MyCounter)
SET@MyCounter=@MyCounter+1ENDGOSETNOCOUNTOFFGOselect*fromTestTable--droptableTestTable
我看一下,突然想到一个使用变量的方法来实现,如下:我看一下,突然想到一个使用变量的方法来实现,如下:
--建一个200行数据的测试表#TempDECLARE@iintCREATETABLE#Temp([id]int,C1nvarchar(20),BHint)SET@i=1WHILE@i<=200BEGININSERTINTO#TempSELECT@i,CAST(@i+rand()asnvarchar(20)),nullSET@i=@i+1ENDSELECT*FROM#Temp--更新字段BH,更新行数为前100行SET@i=0UPDATE#TempSET@i=@i+1,BH=@iWHERE[id]IN(SELECTTOP100[id]FROM#Temp)SELECT*FROM#TempDROPTABLE#Temp