常用SQL命令

SELECT @@SERVERNAME  结果:guolei
=============================================================================================================================
选择出重复的字段
SELECT id
FROM [temp]
WHERE (SELECT COUNT(*)
          FROM (SELECT *
                  FROM TEMP) AS aa
          WHERE aa.id = TEMP .id) > 1

INSERT INTO temp1
      (id, SUM) (SELECT ziduan1, SUM(ziduan2)
                 FROM TEMP
                 GROUP BY ziduan1)

选择出重复的字段
SELECT id
FROM [temp]
WHERE (SELECT COUNT(*)
          FROM (SELECT *
                  FROM TEMP) AS aa
          WHERE aa.id = TEMP .id) > 1
SELECT *, COUNT(*) AS 重复记录数
FROM [temp]
GROUP BY ziduan1, ziduan2

WITH temp(...,...) AS
(
  select ...
)
select ... from temp
group by ..
having ...
with子句中的select用来返回一系列结果
存放在临时表temp中
后一个Select从temp中取出数据分组。
此语句只能在大型数据库中使用。

有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略。
1、对于第一种重复,比较容易解决,使用
    select distinct * from tableName
就可以得到无重复记录的结果集。
如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除
    select distinct * into #Tmp from tableName
    drop table tableName
    select * into tableName from #Tmp
    drop table #Tmp
发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决。

2、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下
    假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集
    select identity(int,1,1) as autoID, * into #Tmp from tableName
    select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID
    select * from #Tmp where autoID in(select autoID from #tmp2)
    最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)

identity的用法
SELECT IDENTITY(int, 1,1) AS ID_Num,*
INTO NewTable
FROM OldTable
把OldTable的全部内容加入到新表NewTable中的去,并在NewTable加一字段ID_NUM.

/

1.把某个字段重新生气序列(从1到n):
DECLARE @i int
Set @i = 0
Update Table1 Set @i = @i + 1,Field1 = @i

2.按成绩排名次
Update 成绩表
Set a.名次 = (
Select Count(*) + 1
From 成绩表 b
Where a.总成绩 < b.总成绩
)
From 成绩表 a

3.查询外部数据库
Select a.*
From OpenRowSet('Microsoft.Jet.OLEDB.4.0','c:/test.mdb';'admin';'',Table1) a

4.查询Excel文件
Select *
From OpenDataSource('Microsoft.Jet.OLEDB.4.0','Data Source="c:/test.xls";User ID=Admin;Password=;Extended properties=Excel 8.0')...Sheet1$

5.在查询中指定排序规则
Select * From Table1 Order By Field1 COLLATE Chinese_PRC_BIN
为什么要指定排序规则呢?参见:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1633985
例,检查数据库中的Pub_Users表中是否存在指定的用户:
Select Count(*) From Pub_Users Where [UserName]='admin' And [PassWord]='aaa' COLLATE Chinese_PRC_BIN
默认比较是不区分大小写的,如果不加COLLATE Chinese_PRC_BIN,那么密码aaa与AAA是等效的,这当然与实际不符.注意的是,每个条件都要指定排序规则,上例中用户名就不区分大小写.


6.Order By的一个小技巧
Order By可以指定列序而不用指定列名,在下面的例子里说明它的用处(注意,第三列未指定别名)
Select a.ID,a.Name,(Select Count(*) From TableB b Where a.ID=b.PID) From TableA a Order By 3
 
//列转行
SELECT Size_Class, MAX(CASE WHEN DisplayIndex = 1 THEN Size1 END) AS S1,
      MAX(CASE WHEN DisplayIndex = 2 THEN Size1 END) AS S2,
      MAX(CASE WHEN DisplayIndex = 3 THEN Size1 END) AS S3,
      MAX(CASE WHEN DisplayIndex = 4 THEN Size1 END) AS S4
FROM Table1
GROUP BY Size_Class
///
SELECT *
FROM Sys_Account
WHERE (ATID LIKE '[1-2]%')
///
延迟查询
str:= 'waitfor delay '''+MaskEdit1.Text+'''Select * From sys_account where aid=''范玉成''';
按照时间查询
str:= 'waitfor time '''+timetostr(DateTimePicker1.Time)+'''Select * From sys_account where aid=''范玉成''';
///
truncate table_name ----------- 删除表中所有行,仍保持表的完整性
drop table table_name --------------- 完全删除表
///
adoconnetcion.execute('insert into 表1 select * from 表2 in "c:/xxx.mdb"')

其中adoconnetcion连接你的第一个access数据库,xxx.mdb是你的第二个数据库

INSERT INTO 表B(字段1,字段2.....)
  SELECT 对应字段1,对应字段2....
  WHERE 关键字 NOT IN (SELECT 表B.关键字 FROM 表B)

想同时对三个字段进行定位查找,但只输入一个参数值,用Locate可以实现吗?
用循环法给Locate赋值,找到就退出.
如:A:Array[1..3] of string=('字段1','字段2','字段3');
for i:=1 to 3 do
ADOTable1.Locate(''+A[1]+'','参数',[]);//
如果找到就break
=============================================================================================================================backup log [Hpcc3OA] with no_log dbcc shrinkdatabase('Hpcc3OA',truncateonly)
=============================================================================================================================
UPDATE Sys_Account
SET AID = REPLACE(AID, '真', '于')
将字段AID中含有'真'的字符替换成'于'
=========================================================================================================================
在SQL中判断某日是星期几
SELECT DATENAME (WEEKDAY,'2006-03-14')
此示例从 GETDATE 返回的日期中提取月份名
SELECT DATENAME(month, getdate()) AS 'Month Name'
SELECT DATEPART(month, GETDATE())
=========================================================================================================================
根据出生年月日算出生肖

declare @dt as datetime
set @dt = '1981 -01-01'
select case when year(@dt)%12 = 0 then '猴'
            when year(@dt)%12 = 1 then '鸡'
            when year(@dt)%12 = 2 then '狗'
            when year(@dt)%12 = 3 then '猪'
            when year(@dt)%12 = 4 then '鼠'
            when year(@dt)%12 = 5 then '牛'
            when year(@dt)%12 = 6 then '虎'
            when year(@dt)%12 = 7 then '兔'
            when year(@dt)%12 = 8 then '龙'
            when year(@dt)%12 = 9 then '蛇'
            when year(@dt)%12 = 10 then '马'
            when year(@dt)%12 = 11 then '羊'
       end as 生肖


如果Query控件用Open方法执行SQL语句,并且所用的SQL语句访问的是一张或几张频繁使用的表,在执行完SQL语句后,一定要调用SQL的FetchAll方法,能大大地减少死锁发生的概率。例如:
  Query1.Close;
  Query1.SQL.Clear;
  Query1.SQL.Add('select * from  AA');
  Query1.Open;
  Query1.FetchAll;

在上述的例子中,如果AA是一张被频繁访问的表,在对这个表执行这一条select语句的同时,如果恰好有其他人对这张表执行删除或更新操作,便有可能发生死锁。Query1.FetchAll这条语句实现的功能是释放加在表AA上的锁,这样死锁的发生概率可以大大减少。避免死锁,对我们将来进行大型数据库开发尤为重要。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

有sites表数据如下
 bh     name
  1     A
  1     A
  1     B
  2     C
  2     C
  2     C
  2     D
  2     F
我想得到的统计结果是
bh   namecount
1    2
2    3

select distinct bh, count(distinct name) from sites group by bh
SELECT bh,count(*) from
(select distinct bh,name from sites)
group by bh

Query1.SQL.Text:='select * from sys_account where atid=1';
Query1.Open;
=============================================================================================================================
表A(消费表),表B(还款表):
      A
-------------------------------------------
客户  日  期  消费金额
甲   2000-1-1  100
乙   2000-2-2  200
丙   2000-2-3  300
丁   2000-3-2  400
甲   2000-3-5  500
乙   2000-3-6  600
      B
-------------------------------------------
客户  日  期  还款金额
甲   2000-1-1  100
乙   2000-2-2  300
丙   2000-2-3  100
甲   2000-3-5  200
求查询语句,得到每个客户欠款余额,如下:
-------------------------------------------
客户  欠款余额
甲    300
乙     500
丙     200
丁    400
SELECT 客户, SUM(tmp) AS 欠款余额
FROM (SELECT 客户, 消费金额 AS tmp
        FROM A
        UNION ALL
        SELECT 客户, - 还款金额
        FROM B) DERIVEDTBL
GROUP BY 客户

((((ISNULL
使用指定的替换值替换 NULL。
下面的示例查找所有书的平均价格,用值 $10.00 替换 titles 表的 price 列中的所有 NULL 条目。
USE pubs
GO
SELECT AVG(ISNULL(price, $10.00))
FROM titles
GO))))

=============================================================================================================================
id  电话
1   123456
2   0427-13150886560
3   0427-7867065
我的这个表里的电话字段有的人写的是汉字,我想查出电话字段里写的是汉字的记录。这样的sql语句怎么写呢?
UniCode()
SELECT * FROM 表 WHERE UniCode(电话)>255
=============================================================================================================================
我现在有个表字段和数据如下:
  X1   A  B
  1    23 34
  2    34 22
  3    46 89
想得到如下结果,就是增加一列,这一列为前两个值中最大的那个
 X1   A   B   C(为前面两个中大的组成)
 1    23  34  34
  2   34  22  34
  3   46  89  89
用SQL如何写?
SELECT atid, did, (CASE WHEN atid > did THEN atid ELSE did END) AS kkk
FROM Sys_Account
=============================================================================================================================
ADOConnection1.BeginTrans;
ADOConnection1.CommitTrans;
ADOConnection1.RollbackTrans;
Database1.StartTransaction;
Database1.Commit;
Database1.Rollback;事务
还是让SQL SERVER自己控制他的事务的好,你把语句写在
QUERY。SQL。ADD(‘begin Tran’)
.......
.......
Query.sql.add('commit') ;
这样的提交很稳定,让数据库自己去处理事务要比DELPHI好,再有
如果你的应用程序死了的话呢,如果你ADO控制事务的话,那么SQL
语句不会回滚的,数据库自己去处理事务的会回滚,不信你自己去试
  if   Database1.InTransaction  then  //InTransaction is True if a transaction is in progress, False otherwise.
  begin
  end;
  Query1.Connection.BeginTrans;
  Query1.Connection.CommitTrans;
  Query1.Connection.RollbackTrans;
TdataBase有个方法 StartTransaction ,调用后,进入显式事务,在调用前,用
TdataBase的InTransaction属性 Check一下是否有正在进行的事务,如果没有,则调用
starttransaction开始一个新事务,事务只到调用commit 或 rollback 结束,否则
又开始一个新事务就会产生异常,这是显式事务。如果不显式调用Tdatabaes的
starttransaction,则Delphi用隐式事务控制数据,隐式事务在Delphi中用得极为
普遍,Table的 Delete Post 都是在隐式事务的控制下,(前提是没有调用Tdatabase
的starttransaction〕,因此,post之后,Sql server是一定会有数据的,否则要么是
程序写错了,要么是盗自版软件,如果是Sql server的问题,那你就发大财了,可以向
微软起诉,我做了那么多程序,二层的程序用显式事务是不多的,三层的其实也不多,
因为大部分工作都能在隐式事务下很好的完成,除非写大型的而且逻辑相当复杂的
程序,为了取得较好性能,以及不使用显式事务就完成不了业务逻辑的情况下才使用,
然而,程序相对来说就难写了,老板要是不加薪,最好还是隐式事务算了。
各位老兄老弟,多看看帮助吧。

标题: 二个表同步更新SQL
--Error
update cusotmer001 set col001 = ( select col001 from cusotmer002
   where cusotmer001.col001 = cusotmer002.col002)

--Right
update cusotmer001 set cusotmer001.col001 = b.col001
 from cusotmer002 as b
 where cusotmer001.col001 = b.col002
///
==================================================================
 ADOQuery1.SQL.Text := 'Select * from 表 ';
    ADOQuery1.Open;
    ADOQuery1.GetFieldNames(ComboBox1.Items); //all字段名
得到所有字段名。
==================================================================
在SQL语句中字段名含有括号时解决方法
例如:一个表aa中字段名为“姓名(cName)”“金额(iQuantity),则在查询时,就写为:
select [姓名(cName)] from aa
select sum([金额(iQuantity)]) from aa

也就是在字段名前后加上[]即可。

=====================================================================
预先定义一个表
ID   cdefine1
1     aa
2     ab
3     bd
4     bb
我需要通过Sql语句找出字段cdefine1的值在字符串aabbcc中有子串的记录 ?
slect ID,cdefine1 from tablename where charindex(cddefine1,'aabbcc',0)>0
CHARINDEX
返回字符串中指定表达式的起始位置。
语法
CHARINDEX ( expression1 , expression2 [ , start_location ] )
参数
expression1
一个表达式,其中包含要寻找的字符的次序。expression1 是一个短字符数据类型分类的表达式。
expression2
一个表达式,通常是一个用于搜索指定序列的列。expression2 属于字符串数据类型分类。
start_location
在 expression2 中搜索 expression1 时的起始字符位置。如果没有给定 start_location,而是一个负数或零,则将从 expression2 的起始位置开始搜索。
返回类型
int
注释
如果 expression1 或 expression2 之一属于 Unicode 数据类型(nvarchar 或 nchar)而另一个不属于,则将另一个转换为 Unicode 数据类型。
如果 expression1 或 expression2 之一为 NULL 值,则当数据库兼容级别为 70 或更大时,CHARINDEX 返回 NULL 值。当数据库兼容级别为 65 或更小时,CHARINDEX 仅在 expression1 和 expression2 都为 NULL 时返回 NULL 值。
如果在 expression2 内没有找到 expression1,则 CHARINDEX 返回 0。

=============================================================================================================================
SET STATISTICS TIME ON
SET STATISTICS IO  ON
select * from sys_account where atid='2'
在消息页面里结果为:
表 'Sys_Account'。扫描计数 1,逻辑读 3 次,物理读 0 次,预读 0 次。
SQL Server 执行时间:
   CPU 时间 = 2 毫秒,耗费时间 = 2 毫秒。

SQL Server 执行时间:
   CPU 时间 = 10 毫秒,耗费时间 = 9 毫秒。
SQL Server 执行时间:
   CPU 时间 = 10 毫秒,耗费时间 = 10 毫秒。
SQL Server 分析和编译时间:
   CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
SQL Server 执行时间:
   CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。

Set statistics IO
显示磁盘活动信息。此信息包括为查询所在使用的表名称,执行扫描的次数,从数据高速缓存和磁盘读取的页数,以及写入高速缓存的页数。默认设置为 OFF。
 Set statistics IO ON 在查询分析器执行查询的时候就可以得到IO磁盘读写等数据
=============================================================================================================================
是这样的,比如我想查找A表中PersonName字段值为 Jame's Bond 的记录,
SELECT *
FROM A
WHERE PersonName = 'Jame's Bond'

问题就出在这儿:SQL语句中的字符串需要用单引号括起来,但如果这个字符串本身就包含了单引号,怎么办?
望各位赐教
SELECT *
FROM A
WHERE PersonName = 'Jame''s Bond'  //SQL SERVER 中的SQL中的写法

str:='SELECT * FROM Sys_Account WHERE AID =''tom''+''''''''+''s''';  //在DELPHI中的写法
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Add(str);
Query1.Open;
=====================================================================
怎么能一条一条地取出一个数据库中所有的表名 用游标吧;
declare @tableName nvarchar(128)

declare myCursor cursor for
select [name] from sysobjects where xtype = 'U'

open myCursor

fetch next from mycursor into @TableName

while @@Fetch_Status = 0
begin
  print @TableName

  fetch next from mycursor into @TableName
end

close mycursor
deallocate mycursor
=====================================================================
用ADOQuery1调用SQLServer的存储过程,怎么取回返回值
存储过程如下:
CREATE PROCEDURE dt_Test
   (@aa varchar(2000), @bb varchar(2000) OUTPUT)
   AS
   BEGIN
       ....
   END

调用如下:
var
str: string;
begin
   adoq.Close;
   adoq.SQL.Clear;
   adoq.SQL.Add('Execute dt_Test ' + QuotedStr('adfad') + ', :Results');
   adoq.Parameters.ParamByName('Results').DataType := ftString;
   adoq.Prepared;
   adoq.ExecSQL;
   str := adoq.Parameters.ParamByName('Results').Value;
end;

提示类型转换错误。

大家给个方法怎么取得返回值,谢谢了!!
=====================================================================

CREATE PROCEDURE Pro_ReturnDateTime
@ServerDate datetime output
AS
set @ServerDate=getDate()
GO
/*
**设置用户计算机信息
*/

CREATE proc Pro_SetComputerInfo
  @AID varchar(20),
  @ComputerName char(40),
  @ComputerIP char(23),
  @LogName char(20),
  @ComputerComment varchar(1)=null
as
declare @RecoCount int
  if exists (select ComputerName from Sys_Computer where computerName=@ComputerName) 
  begin
    update Sys_Computer
    set AID=@AID,ComputerName=@ComputerName,ComputerIP=@ComputerIP,
          LogName=@LogName,Status=1
    where ComputerName=@computerName 
  end
  else
  begin
    select @RecoCount=max(CID) from Sys_Computer
    insert Sys_Computer(CID,AID,ComputerName,ComputerIP,LogName,Status)
    values(@RecoCount+1,@AID,@ComputerName,@ComputerIP,@LogName,1)
  end
GO
sgAID
  end
  CLOSE find1
  DEALLOCATE find1

/**********************检查收文待承办消息***********************/
declare find2 CURSOR FOR /*游标 用于轮循结果集*/

  select DAID,AID from DocAcceptCheck where YesOrNo=2
  open find2
  FETCH NEXT From find2
  INTO @MsgValue,@MsgAID
  While @@FETCH_STATUS = 0
  begin
       update Sys_Message
       set YesOrNo=1
       where MsgValue=@MsgValue and MsgAID=@MsgAID
   
  FETCH NEXT FROM find2
  INTO @MsgValue,@MsgAID
  end
  CLOSE find2
  DEALLOCATE find2

/**********************检查发文待批阅消息***********************/
declare find3 CURSOR FOR /*游标 用于轮循结果集*/

  select DDID,AID from DocDispatchPostil where YesOrNo=2
  open find3
  FETCH NEXT From find3
  INTO @MsgValue,@MsgAID
  While @@FETCH_STATUS = 0
  begin
       update Sys_Message
       set YesOrNo=1
       where MsgValue=@MsgValue and MsgAID=@MsgAID
   
  FETCH NEXT FROM find3
  INTO @MsgValue,@MsgAID
  end
  CLOSE find3
  DEALLOCATE find3

/**********************检查发文待承办消息***********************/
declare find4 CURSOR FOR /*游标 用于轮循结果集*/

  select DDID,AID from DocDispatchSend where YesOrNo=2
  open find4
  FETCH NEXT From find4
  INTO @MsgValue,@MsgAID
  While @@FETCH_STATUS = 0
  begin
       update Sys_Message
       set YesOrNo=1
       where MsgValue=@MsgValue and MsgAID=@MsgAID
   
  FETCH NEXT FROM find4
  INTO @MsgValue,@MsgAID
  end
  CLOSE find4
  DEALLOCATE find4

/**********************检查部门工作计划消息***********************/
declare find5 CURSOR FOR /*游标 用于轮循结果集*/

  select PID,LID from DepartmentProjectBase where Status=2
  open find5
  FETCH NEXT From find5
  INTO @MsgValue,@MsgAID
  While @@FETCH_STATUS = 0
  begin
       update Sys_Message
       set YesOrNo=1
       where MsgValue=@MsgValue and MsgAID=@MsgAID
   
  FETCH NEXT FROM find5
  INTO @MsgValue,@MsgAID
  end
  CLOSE find5
  DEALLOCATE find5

/**********************检查会议通知***********************/
declare find6 CURSOR FOR /*游标 用于轮循结果集*/

  select MID,AID from MeetingNotify where Status=1
  open find6
  FETCH NEXT From find6
  INTO @MsgValue,@MsgAID
  While @@FETCH_STATUS = 0
  begin
       update Sys_Message
       set YesOrNo=1
       where MsgValue=@MsgValue and MsgAID=@MsgAID
   
  FETCH NEXT FROM find6
  INTO @MsgValue,@MsgAID
  end
  CLOSE find6
  DEALLOCATE find6
GO
相关 and 收文号与要添加的收文号相同 and  消息目标与要添加的目标相同 */
    if not exists(select *from Sys_Message  where MsgType=1 and MsgValue=@MsgValue and MsgAID=@MsgAID)
    begin
       select @RecCount=count(*) from Sys_Message
       select @MsgContent=Title from DocAcceptBase where DAID=@MsgValue
       set @MsgType=1
       set @MsgContent='主题为:'+' " '+@MsgContent+' " '+'的收文需要您批阅.'
       insert Sys_Message (MsgID,MsgType,MsgValue,MsgContent,MsgAID)
       values (@RecCount+1,@MsgType,@MsgValue,@MsgContent,@MsgAID)
    end
  FETCH NEXT FROM find1
  INTO @MsgValue, @MsgAID
  end
  CLOSE find1
  DEALLOCATE find1

declare find2 CURSOR FOR /*游标 用于轮循结果集*/
  /****************检索收文待承办表*************************************/
  select DAID,AID from DocAcceptCheck where YesOrNo=1
  open find2
  FETCH NEXT From find2
  INTO @MsgValue, @MsgAID
  While @@FETCH_STATUS = 0
  begin
    /*是否存在这样的消息记录 收文相关 and 收文号与要添加的收文号相同 and  消息目标与要添加的目标相同 */
    if not exists(select *from Sys_Message  where MsgType=1 and MsgValue=@MsgValue and MsgAID=@MsgAID)
    begin
       select @RecCount=count(*) from Sys_Message
       select @MsgContent=Title from DocAcceptBase where DAID=@MsgValue
       set @MsgType=1
       set @MsgContent='主题为:'+' " '+@MsgContent+' " '+'的收文需要您承办.'
       insert Sys_Message (MsgID,MsgType,MsgValue,MsgContent,MsgAID)
       values (@RecCount+1,@MsgType,@MsgValue,@MsgContent,@MsgAID)
    end
  FETCH NEXT FROM find2
  INTO @MsgValue, @MsgAID
  end
  CLOSE find2
  DEALLOCATE find2

declare find3 CURSOR FOR /*游标 用于轮循结果集*/
  /****************检索发文待批阅表*************************************/
  select DDID,AID from DocDispatchPostil where YesOrNo=1
  open find3
  FETCH NEXT From find3
  INTO @MsgValue, @MsgAID
  While @@FETCH_STATUS = 0
  begin
    /*是否存在这样的消息记录 发文相关 and 发文号与要添加的收文号相同 and  消息目标与要添加的目标相同 */
    if not exists(select *from Sys_Message  where MsgType=2 and MsgValue=@MsgValue and MsgAID=@MsgAID)
    begin
       select @RecCount=count(*) from Sys_Message
       select @MsgContent=Title from DocDispatchBase where DDID=@MsgValue
       set @MsgType=2
       set @MsgContent='主题为:'+' " '+@MsgContent+' " '+'的发文需要您批阅.'
       insert Sys_Message (MsgID,MsgType,MsgValue,MsgContent,MsgAID)
       values (@RecCount+1,@MsgType,@MsgValue,@MsgContent,@MsgAID)
    end
  FETCH NEXT FROM find3
  INTO @MsgValue, @MsgAID
  end
  CLOSE find3
  DEALLOCATE find3

declare find4 CURSOR FOR /*游标 用于轮循结果集*/
  /****************检索发文待接收表*************************************/
  select DDID,AID from DocDispatchSend where YesOrNo=1
  open find4
  FETCH NEXT From find4
  INTO @MsgValue, @MsgAID
  While @@FETCH_STATUS = 0
  begin
    /*是否存在这样的消息记录 发文相关 and 发文号与要添加的收文号相同 and  消息目标与要添加的目标相同 */
    if not exists(select *from Sys_Message  where MsgType=2 and MsgValue=@MsgValue and MsgAID=@MsgAID)
    begin
       select @RecCount=count(*) from Sys_Message
       select @MsgContent=Title from DocDispatchBase where DDID=@MsgValue
       set @MsgType=2
       set @MsgContent='主题为:'+' " '+@MsgContent+' " '+'的发文需要您接收.'
       insert Sys_Message (MsgID,MsgType,MsgValue,MsgContent,MsgAID)
       values (@RecCount+1,@MsgType,@MsgValue,@MsgContent,@MsgAID)
    end
  FETCH NEXT FROM find4
  INTO @MsgValue, @MsgAID
  end
  CLOSE find4
  DEALLOCATE find4

declare find5 CURSOR FOR /*游标 用于轮循结果集*/
  /****************检索会议通知待接收表*************************************/
  select MID,AID from MeetingNotify where Status=0
  open find5
  FETCH NEXT From find5
  INTO @MsgValue, @MsgAID
  While @@FETCH_STATUS = 0
  begin
    /*是否存在这样的消息记录 会议相关 and 会议号与要添加的会议号相同 and  消息目标与要添加的目标相同 */
    if not exists(select *from Sys_Message  where MsgType=3 and MsgValue=@MsgValue and MsgAID=@MsgAID)
    begin
       select @RecCount=count(*) from Sys_Message
       select @MsgContent=Title from MeetingBase where MID=@MsgValue
       set @MsgType=3
       set @MsgContent='主题为:'+' " '+@MsgContent+' " '+'的会议需要您参加.'
       insert Sys_Message (MsgID,MsgType,MsgValue,MsgContent,MsgAID)
       values (@RecCount+1,@MsgType,@MsgValue,@MsgContent,@MsgAID)
    end
  FETCH NEXT FROM find5
  INTO @MsgValue, @MsgAID
  end
  CLOSE find5
  DEALLOCATE find5

declare find6 CURSOR FOR /*游标 用于轮循结果集*/
  /****************检索部门工作计划表*************************************/
  select PID,LID,Title from DepartmentProjectBase where Status=1
  open find6
  FETCH NEXT From find6
  INTO @MsgValue, @MsgAID, @MsgContent
  While @@FETCH_STATUS = 0
  begin
    /*是否存在这样的消息记录 计划相关 and 计划号与要添加的计划号相同 and  消息目标与要添加的目标相同 */
    if not exists(select *from Sys_Message  where MsgType=4 and MsgValue=@MsgValue and MsgAID=@MsgAID)
    begin
       select @RecCount=count(*) from Sys_Message
       set @MsgType=4
       set @MsgContent='主题为:'+' " '+@MsgContent+' " '+'的部门工作计划需要您批阅.'
       insert Sys_Message (MsgID,MsgType,MsgValue,MsgContent,MsgAID)
       values (@RecCount+1,@MsgType,@MsgValue,@MsgContent,@MsgAID)
    end
  FETCH NEXT FROM find6
  INTO @MsgValue, @MsgAID, @MsgContent
  end
  CLOSE find6
  DEALLOCATE find6

declare find7 CURSOR FOR /*游标 用于轮循结果集*/
  /****************检索部门工作计划具体工作安排表*************************************/
  select PID,OID,Content from DepartmentProjectContent where Agree=1
  open find7
  FETCH NEXT From find7
  INTO @MsgValue, @MsgAID, @MsgContent
  While @@FETCH_STATUS = 0
  begin
    /*是否存在这样的消息记录 计划相关 and 计划号与要添加的计划号相同 and  消息目标与要添加的目标相同 */
    if not exists(select *from Sys_Message  where MsgType=5 and MsgValue=@MsgValue and MsgAID=@MsgAID)
    begin
       select @RecCount=count(*) from Sys_Message
       set @MsgType=5
       set @MsgContent='内容为:'+' " '+@MsgContent+' " '+'的上级工作安排需要您办理.'
       insert Sys_Message (MsgID,MsgType,MsgValue,MsgContent,MsgAID)
       values (@RecCount+1,@MsgType,@MsgValue,@MsgContent,@MsgAID)
    end
  FETCH NEXT FROM find7
  INTO @MsgValue, @MsgAID, @MsgContent
  end
  CLOSE find7
  DEALLOCATE find7
GO

保存 评价 游戏规则 免费注册  资料下载 关于本站 
问题分类 编程问题 非技术题 富翁列表 我的信息 提出问题 在线富翁 富翁日历 笔记列表 我的笔记 写作笔记 全文检索 《专家门诊》 


 
富翁名称
富翁密码

 请记住我

富翁名称


免费注册


--------------------------------------------------------------------------------


--------------------------------------------------------------------------------

大富翁论坛版权所有
 KeyLife富翁笔记 
作者: yuanyoufa
标题: sql用法!!
关键字:
分类: 个人专区
密级: 公开
(评分: , 回复: 0, 阅读: 176) ??
1.数据库查询:Select用法
Select [Top(数值)] 字段列表 From 数据表 [Where 条件] [Order by 字段] [asc或desc]

2.添加数据:Insert Into用法
Insert Into 数据表(字段1,字段2,字段3,…) Values(字段1的值,字段2的值,字段3的值,…)

3.删除数据:Delete用法
Delete From 数据表 [Where 条件]

4.更新数据:Update用法
Update 数据表 Set 字段1=字段值1, 字段2=字段值2, … [Where 条件]

5.建数据表:Create Table用法
Create Table 数据表名(字段1名称,字段1类型,字段2名称 字段2类型, …)

Access数据表常用数据类型:Text,Char(Number),Memo,Number,Int,Date/Time,Logical,OLEObject

自动编号字段添加例子:create table aaa(id int identity (1, 1) not null,abc varchar(25) null)

6.改数据表:Alter Table用法
添加字段:Alter Table 数据表名 Add Column 字段名 字段类型

删除字段:Alter Table 数据表名 Drop Column 字段名

7.删数据表:Drop Table用法

Drop Table 数据表名

*******************Transact_SQL********************

Alter Table [表] Alter [id] Counter Constraint [表_p] Primary Key 把id列改为自动编号类型,并且设置为主键

--语 句 功 能
--数据操作
SELECT --从数据库表中检索数据行和列
INSERT --向数据库表添加新数据行
DELETE --从数据库表中删除数据行
UPDATE --更新数据库表中的数据
--数据定义
CREATE TABLE --创建一个数据库表
DROP TABLE --从数据库中删除表
ALTER TABLE --修改数据库表结构
CREATE VIEW --创建一个视图
DROP VIEW --从数据库中删除视图
CREATE INDEX --为数据库表创建一个索引
DROP INDEX --从数据库中删除索引
CREATE PROCEDURE --创建一个存储过程
DROP PROCEDURE --从数据库中删除存储过程
CREATE TRIGGER --创建一个触发器
DROP TRIGGER --从数据库中删除触发器
CREATE SCHEMA --向数据库添加一个新模式
DROP SCHEMA --从数据库中删除一个模式
CREATE DOMAIN --创建一个数据值域
ALTER DOMAIN --改变域定义
DROP DOMAIN --从数据库中删除一个域
--数据控制
GRANT --授予用户访问权限
DENY --拒绝用户访问
REVOKE --解除用户访问权限
--事务控制
COMMIT --结束当前事务
ROLLBACK --中止当前事务
SET TRANSACTION --定义当前事务数据访问特征
--程序化SQL
DECLARE --为查询设定游标
EXPLAN --为查询描述数据访问计划
OPEN --检索查询结果打开一个游标
FETCH --检索一行查询结果
CLOSE --关闭游标
PREPARE --为动态执行准备SQL 语句
EXECUTE --动态地执行SQL 语句
DESCRIBE --描述准备好的查询

---局部变量
declare @id char(10)
--set @id = '10010001'
select @id = '10010001'

---全局变量
---必须以@@开头

--IF ELSE
declare @x int @y int @z int
select @x = 1 @y = 2 @z=3
if @x > @y
print 'x > y' --打印字符串'x > y'
else if @y > @z
print 'y > z'
else print 'z > y'

--CASE
use pangu
update employee
set e_wage =
case
when job_level = ’1’ then e_wage*1.08
when job_level = ’2’ then e_wage*1.07
when job_level = ’3’ then e_wage*1.06
else e_wage*1.05
end

--WHILE CONTINUE BREAK
declare @x int @y int @c int
select @x = 1 @y=1
while @x < 3
begin
print @x --打印变量x 的值
while @y < 3
begin
select @c = 100*@x + @y
print @c --打印变量c 的值
select @y = @y + 1
end
select @x = @x + 1
select @y = 1
end

--WAITFOR
--例 等待1 小时2 分零3 秒后才执行SELECT 语句
waitfor delay ’01:02:03’
select * from employee
--例 等到晚上11 点零8 分后才执行SELECT 语句
waitfor time ’23:08:00’
select * from employee

***SELECT***

select *(列名) from table_name(表名) where column_name operator value
ex:(宿主)
select * from stock_information where stockid = str(nid)
stockname = 'str_name'
stockname like '% find this %'
stockname like '[a-zA-Z]%' --------- ([]指定值的范围)
stockname like '[^F-M]%' --------- (^排除指定范围)
--------- 只能在使用like关键字的where子句中使用通配符)
or stockpath = 'stock_path'
or stocknumber < 1000
and stockindex = 24
not stocksex = 'man'
stocknumber between 20 and 100
stocknumber in(10,20,30)
order by stockid desc(asc) --------- 排序,desc-降序,asc-升序
order by 1,2 --------- by列号
stockname = (select stockname from stock_information where stockid = 4)
--------- 子查询
--------- 除非能确保内层select只返回一个行的值,
--------- 否则应在外层where子句中用一个in限定符
select distinct column_name form table_name --------- distinct指定检索独有的列值,不重复
select stocknumber ,"stocknumber + 10" = stocknumber + 10 from table_name
select stockname , "stocknumber" = count(*) from table_name group by stockname
--------- group by 将表按行分组,指定列中有相同的值
having count(*) = 2 --------- having选定指定的组

select *
from table1, table2
where table1.id *= table2.id -------- 左外部连接,table1中有的而table2中没有得以null表示
table1.id =* table2.id -------- 右外部连接

select stockname from table1
union [all] ----- union合并查询结果集,all-保留重复行
select stockname from table2

***insert***

insert into table_name (Stock_name,Stock_number) value ("xxx","xxxx")
value (select Stockname , Stocknumber from Stock_table2)---value为select语句

***update***

update table_name set Stockname = "xxx" [where Stockid = 3]
Stockname = default
Stockname = null
Stocknumber = Stockname + 4

***delete***

delete from table_name where Stockid = 3
truncate table_name ----------- 删除表中所有行,仍保持表的完整性
drop table table_name --------------- 完全删除表

***alter table*** --- 修改数据库表结构

alter table database.owner.table_name add column_name char(2) null .....
sp_help table_name ---- 显示表已有特征
create table table_name (name char(20), age smallint, lname varchar(30))
insert into table_name select ......... ----- 实现删除列的方法(创建新表)
alter table table_name drop constraint Stockname_default ---- 删除Stockname的default约束

***function(/*常用函数*/)***

----统计函数----
AVG --求平均值
COUNT --统计数目
MAX --求最大值
MIN --求最小值
SUM --求和

--AVG
use pangu
select avg(e_wage) as dept_avgWage
from employee
group by dept_id

--MAX
--求工资最高的员工姓名
use pangu
select e_name
from employee
where e_wage =
(select max(e_wage)
from employee)

--STDEV()
--STDEV()函数返回表达式中所有数据的标准差

--STDEVP()
--STDEVP()函数返回总体标准差

--VAR()
--VAR()函数返回表达式中所有值的统计变异数

--VARP()
--VARP()函数返回总体变异数

----算术函数----

/***三角函数***/
SIN(float_expression) --返回以弧度表示的角的正弦
COS(float_expression) --返回以弧度表示的角的余弦
TAN(float_expression) --返回以弧度表示的角的正切
COT(float_expression) --返回以弧度表示的角的余切
/***反三角函数***/
ASIN(float_expression) --返回正弦是FLOAT 值的以弧度表示的角
ACOS(float_expression) --返回余弦是FLOAT 值的以弧度表示的角
ATAN(float_expression) --返回正切是FLOAT 值的以弧度表示的角
ATAN2(float_expression1,float_expression2)
--返回正切是float_expression1 /float_expres-sion2的以弧度表示的角
DEGREES(numeric_expression)
--把弧度转换为角度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT 类型
RADIANS(numeric_expression) --把角度转换为弧度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT 类型
EXP(float_expression) --返回表达式的指数值
LOG(float_expression) --返回表达式的自然对数值
LOG10(float_expression)--返回表达式的以10 为底的对数值
SQRT(float_expression) --返回表达式的平方根
/***取近似值函数***/
CEILING(numeric_expression) --返回>=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
FLOOR(numeric_expression) --返回<=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
ROUND(numeric_expression) --返回以integer_expression 为精度的四舍五入值返回的数据
--类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
ABS(numeric_expression) --返回表达式的绝对值返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
SIGN(numeric_expression) --测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型
--与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
PI() --返回值为π 即3.1415926535897936
RAND([integer_expression]) --用任选的[integer_expression]做种子值得出0-1 间的随机浮点数

----字符串函数----
ASCII() --函数返回字符表达式最左端字符的ASCII 码值
CHAR() --函数用于将ASCII 码转换为字符
--如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值
LOWER() --函数把字符串全部转换为小写
UPPER() --函数把字符串全部转换为大写
STR() --函数把数值型数据转换为字符型数据
LTRIM() --函数把字符串头部的空格去掉
RTRIM() --函数把字符串尾部的空格去掉
LEFT(),RIGHT(),SUBSTRING() --函数返回部分字符串
CHARINDEX(),PATINDEX() --函数返回字符串中某个指定的子串出现的开始位置
SOUNDEX() --函数返回一个四位字符码
--SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值
DIFFERENCE() --函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异
--0 两个SOUNDEX 函数返回值的第一个字符不同
--1 两个SOUNDEX 函数返回值的第一个字符相同
--2 两个SOUNDEX 函数返回值的第一二个字符相同
--3 两个SOUNDEX 函数返回值的第一二三个字符相同
--4 两个SOUNDEX 函数返回值完全相同


QUOTENAME() --函数返回被特定字符括起来的字符串
/*select quotename('abc', '{') quotename('abc')
运行结果如下
----------------------------------{
{abc} [abc]*/

REPLICATE() --函数返回一个重复character_expression 指定次数的字符串
/*select replicate('abc', 3) replicate( 'abc', -2)
运行结果如下
----------- -----------
abcabcabc NULL*/

REVERSE() --函数将指定的字符串的字符排列顺序颠倒
REPLACE() --函数返回被替换了指定子串的字符串
/*select replace('abc123g', '123', 'def')
运行结果如下
----------- -----------
abcdefg*/

SPACE() --函数返回一个有指定长度的空白字符串
STUFF() --函数用另一子串替换字符串指定位置长度的子串

----数据类型转换函数----
CAST() 函数语法如下
CAST() ( AS [ length ])
CONVERT() 函数语法如下
CONVERT() ([ length ], [, style])

select cast(100+99 as char) convert(varchar(12), getdate())
运行结果如下
------------------------------ ------------
199 Jan 15 2000

----日期函数----
DAY() --函数返回date_expression 中的日期值
MONTH() --函数返回date_expression 中的月份值
YEAR() --函数返回date_expression 中的年份值
DATEADD( , ,)
--函数返回指定日期date 加上指定的额外日期间隔number 产生的新日期
DATEDIFF( , ,)
--函数返回两个指定日期在datepart 方面的不同之处
DATENAME( , ) --函数以字符串的形式返回日期的指定部分
DATEPART( , ) --函数以整数值的形式返回日期的指定部分
GETDATE() --函数以DATETIME 的缺省格式返回系统当前的日期和时间

----系统函数----
APP_NAME() --函数返回当前执行的应用程序的名称
COALESCE() --函数返回众多表达式中第一个非NULL 表达式的值
COL_LENGTH(<'table_name'>, <'column_name'>) --函数返回表中指定字段的长度值
COL_NAME(, ) --函数返回表中指定字段的名称即列名
DATALENGTH() --函数返回数据表达式的数据的实际长度
DB_ID(['database_name']) --函数返回数据库的编号
DB_NAME(database_id) --函数返回数据库的名称
HOST_ID() --函数返回服务器端计算机的名称
HOST_NAME() --函数返回服务器端计算机的名称
IDENTITY([, seed increment]) [AS column_name])
--IDENTITY() 函数只在SELECT INTO 语句中使用用于插入一个identity column列到新表中
/*select identity(int, 1, 1) as column_name
into newtable
from oldtable*/
ISDATE() --函数判断所给定的表达式是否为合理日期
ISNULL(, ) --函数将表达式中的NULL 值用指定值替换
ISNUMERIC() --函数判断所给定的表达式是否为合理的数值
NEWID() --函数返回一个UNIQUEIDENTIFIER 类型的数值
NULLIF(, )
--NULLIF 函数在expression1 与expression2 相等时返回NULL 值若不相等时则返回expression1 的值
单查询

  简单的Transact-SQL查询只包括选择列表、FROM子句和WHERE子句。它们分别说明所查询列、查询的表或视图、以及搜索条件等。
  例如,下面的语句查询testtable表中姓名为“张三”的nickname字段和email字段。


 


   SELECT nickname,email
  FROM testtable
  WHERE name='张三'


  (一) 选择列表

  选择列表(select_list)指出所查询列,它可以是一组列名列表、星号、表达式、变量(包括局部变量和全局变量)等构成。

  1、选择所有列

  例如,下面语句显示testtable表中所有列的数据:

   SELECT *
  FROM testtable

  2、选择部分列并指定它们的显示次序

  查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。
  例如:

   SELECT nickname,email
  FROM testtable

  3、更改列标题

  在选择列表中,可重新指定列标题。定义格式为:
  列标题=列名
  列名 列标题
  如果指定的列标题不是标准的标识符格式时,应使用引号定界符,例如,下列语句使用汉字显示列标题:

   SELECT 昵称=nickname,电子邮件=email
  FROM testtable


  4、删除重复行

  SELECT语句中使用ALL或DISTINCT选项来显示表中符合条件的所有行或删除其中重复的数据行,默认为ALL。使用DISTINCT选项时,对于所有重复的数据行在SELECT返回的结果集合中只保留一行。

  5、限制返回的行数

  使用TOP n [PERCENT]选项限制返回的数据行数,TOP n说明返回n行,而TOP n PERCENT时,说明n是表示一百分数,指定返回的行数等于总行数的百分之几。
  例如:

   SELECT TOP 2 *
  FROM testtable
  SELECT TOP 20 PERCENT *
  FROM testtable


  (二)FROM子句

  FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔。
  在FROM子句同时指定多个表或视图时,如果选择列表中存在同名列,这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定:


   SELECT username,citytable.cityid
  FROM usertable,citytable
  WHERE usertable.cityid=citytable.cityid

  在FROM子句中可用以下两种格式为表或视图指定别名:
  表名 as 别名
  表名 别名

) FROM子句

  FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔。
  在FROM子句同时指定多个表或视图时,如果选择列表中存在同名列,这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定:

   SELECT username,citytable.cityid
  FROM usertable,citytable
  WHERE usertable.cityid=citytable.cityid

  在FROM子句中可用以下两种格式为表或视图指定别名:
  表名 as 别名
  表名 别名
  例如上面语句可用表的别名格式表示为:

   SELECT username,b.cityid
  FROM usertable a,citytable b
  WHERE a.cityid=b.cityid

  SELECT不仅能从表或视图中检索数据,它还能够从其它查询语句所返回的结果集合中查询数据。

  例如:

   SELECT a.au_fname+a.au_lname
  FROM authors a,titleauthor ta
  (SELECT title_id,title
  FROM titles
  WHERE ytd_sales>10000
  ) AS t
  WHERE a.au_id=ta.au_id
  AND ta.title_id=t.title_id

  此例中,将SELECT返回的结果集合给予一别名t,然后再从中检索数据。

  (三) 使用WHERE子句设置查询条件

  WHERE子句设置查询条件,过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据:

   SELECT *
  FROM usertable
  WHERE age>20

  WHERE子句可包括各种条件运算符:
  比较运算符(大小比较):>、>=、=、<、<=、<>、!>、!<
  范围运算符(表达式值是否在指定的范围):BETWEEN…AND…
  NOT BETWEEN…AND…
  列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2……)
  NOT IN (项1,项2……)
  模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE
  空值判断符(判断表达式是否为空):IS NULL、NOT IS NULL
  逻辑运算符(用于多条件的逻辑连接):NOT、AND、OR

  1、范围运算符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30
  2、列表运算符例:country IN ('Germany','China')
  3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配。可用于char、varchar、text、ntext、datetime和smalldatetime等类型查询。
  可使用以下通配字符:
  百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%%。
  下划线_:匹配单个任意字符,它常用来限制表达式的字符长度。
  方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。[^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符。
  例如:
  限制以Publishing结尾,使用LIKE '%Publishing'
  限制以A开头:LIKE '[A]%'
  限制以A开头外:LIKE '[^A]%'

4、空值判断符
例WHERE age IS NULL

  5、逻辑运算符:优先级为NOT、AND、OR

  (四)查询结果排序

  使用ORDER BY子句对查询返回的结果按一列或多列排序。ORDER BY子句的语法格式为:
  ORDER BY {column_name [ASC|DESC]} [,…n]
  其中ASC表示升序,为默认值,DESC为降序。ORDER BY不能按ntext、text和image数据类型进行排
  序。
  例如:

   SELECT *
  FROM usertable
  ORDER BY age desc,userid ASC

  另外,可以根据表达式进行排序。

  二、 联合查询

  UNION运算符可以将两个或两个以上上SELECT语句的查询结果集合合并成一个结果集合显示,即执行联合查询。UNION的语法格式为:

   select_statement
  UNION [ALL] selectstatement
  [UNION [ALL] selectstatement][…n]

  其中selectstatement为待联合的SELECT查询语句。

  ALL选项表示将所有行合并到结果集合中。不指定该项时,被联合查询结果集合中的重复行将只保留一行。

  联合查询时,查询结果的列标题为第一个查询语句的列标题。因此,要定义列标题必须在第一个查询语句中定义。要对联合查询结果排序时,也必须使用第一查询语句中的列名、列标题或者列序号。


  在使用UNION 运算符时,应保证每个联合查询语句的选择列表中有相同数量的表达式,并且每个查询选择表达式应具有相同的数据类型,或是可以自动将它们转换为相同的数据类型。在自动转换时,对于数值类型,系统将低精度的数据类型转换为高精度的数据类型。

  在包括多个查询的UNION语句中,其执行顺序是自左至右,使用括号可以改变这一执行顺序。例如:

  查询1 UNION (查询2 UNION 查询3)

  三、连接查询

  通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。

  在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,尔后通过连接进行查询。

  连接可以在SELECT 语句的FROM子句或WHERE子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与WHERE子句中的搜索条件区分开来。所以,在Transact-SQL中推荐使用这种方法。

  SQL-92标准所定义的FROM子句的连接语法格式为:

   FROM join_table join_type join_table
  [ON (join_condition)]

  其中join_table指出参与连接操作的表名,连接可以对同一个表操作,也可以对多表操作,对同一个表操作的连接又称做自连接。

 
join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。


  交叉连接(CROSS JOIN)没有WHERE 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。

  连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成。

  无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接。例如:

   SELECT p1.pub_id,p2.pub_id,p1.pr_info
  FROM pub_info AS p1 INNER JOIN pub_info AS p2
  ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)

  (一)内连接
  内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。内连接分三种:
  1、等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。
  2、不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。
  3、自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。
  例,下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社:

   SELECT *
  FROM authors AS a INNER JOIN publishers AS p
  ON a.city=p.city
  又如使用自然连接,在选择列表中删除authors 和publishers 表中重复列(city和state):
  SELECT a.*,p.pub_id,p.pub_name,p.country
  FROM authors AS a INNER JOIN publishers AS p
  ON a.city=p.city

  (二)外连接
  内连接时,返回查询结果集合中的仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。如下面使用左外连接将论坛内容和作者信息连接起来:

   SELECT a.*,b.* FROM luntan LEFT JOIN usertable as b
  ON a.username=b.username

  下面使用全外连接将city表中的所有作者以及user表中的所有作者,以及他们所在的城市:

   SELECT a.*,b.*
  FROM city as a FULL OUTER JOIN user as b
  ON a.username=b.username


  (三)交叉连接
  交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等

   于6*8=48行。
  SELECT type,pub_name
  FROM titles CROSS JOIN publishers
  ORDER BY type
  [Post=0][/Post]

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------

大富翁论坛版权所有
 KeyLife富翁笔记 
作者: snowspace1981
标题: sql优化
关键字: sql优化
分类: Sql
密级: 公开
(评分: , 回复: 0, 阅读: 248) ??
1.合理使用索引
索引是数据库中重要的数据结构,它的根本目的就是为了提高查询效率。现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构。索引的使用要恰到好处,其使用原则如下:
●在经常进行连接,但是没有指定为外键的列上建立索引,而不经常连接的字段则由优化器自动生成索引。
●在频繁进行排序或分组(即进行group by或order by操作)的列上建立索引。
●在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值,因此就无必要建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。
●如果待排序的列有多个,可以在这些列上建立复合索引(compound index)。
●使用系统工具。如Informix数据库有一个tbcheck工具,可以在可疑的索引上进行检查。在一些数据库服务器上,索引可能失效或者因为频繁操作而使得读取效率降低,如果一个使用索引的查询不明不白地慢下来,可以试着用tbcheck工具检查索引的完整性,必要时进行修复。另外,当数据库表更新大量数据后,删除并重建索引可以提高查询速度。

(1)在下面两条select语句中:
   select * from table1  where  field1<=10000 and field1>=0;
   select * from table1  where  field1>=0 and field1<=10000;
   如果数据表中的数据field1都>=0,则第一条select语句要比第二条select语句效率高的多,因为第二条select语句的第一个条件耗费了大量的系统资源。
   第一个原则:在where子句中应把最具限制性的条件放在最前面。

(2)在下面的select语句中:
   select * from tab  where  a=… and b=… and c=…;
  若有索引index(a,b,c),则where子句中字段的顺序应和索引中字段顺序一致。
   第二个原则:where子句中字段的顺序应和索引中字段顺序一致。

以下假设在field1上有唯一索引I1,在field2上有非唯一索引I2。
(3) select field3,field4 from tb where field1='sdf'        快
    select * from tb where field1='sdf'      慢,
因为后者在索引扫描后要多一步ROWID表访问。

(4) select field3,field4 from tb where field1>='sdf'        快
select field3,field4 from tb where field1>'sdf'        慢
因为前者可以迅速定位索引。

(5) select field3,field4 from tb where field2 like 'R%'    快
    select field3,field4 from tb where field2 like '%R'    慢,
    因为后者不使用索引。

(6) 使用函数如:
select field3,field4 from tb where upper(field2)='RMN'不使用索引。
如果一个表有两万条记录,建议不使用函数;如果一个表有五万条以上记录,严格禁止使用函数!两万条记录以下没有限制。

(7) 空值不在索引中存储,所以
    select field3,field4 from tb where field2 is[not] null不使用索引。

(8) 不等式如
    select field3,field4 from tb where field2!='TOM'不使用索引。
    相似地,
    select field3,field4 from tb where field2 not in('M','P')不使用索引。

(9) 多列索引,只有当查询中索引首列被用于条件时,索引才能被使用。

(10)  MAX,MIN等函数,如
Select max(field2) from tb使用索引。所以,如果需要对字段取max,min,sum等,应该加索引。
一次只使用一个聚集函数,如:
select “min”=min(field1), “max”=max(field1)  from tb     
不如:select “min”=(select min(field1) from tb) , “max”=(select max(field1) from tb)   

(11) 重复值过多的索引不会被查询优化器使用。而且因为建了索引,修改该字段值时还要修改索引,所以更新该字段的操作比没有索引更慢。

(12) 索引值过大(如在一个char(40)的字段上建索引),会造成大量的I/O开销(甚至会超过表扫描的I/O开销)。因此,尽量使用整数索引。 Sp_estspace可以计算表和索引的开销。

(13) 对于多列索引,order by的顺序必须和索引的字段顺序一致。

(14) 在sybase中,如果order by的字段组成一个簇索引,那么无须做order by。记录的排列顺序是与簇索引一致的。

(15) 多表联结(具体查询方案需要通过测试得到)
    where子句中限定条件尽量使用相关联的字段,且尽量把相关联的字段放在前面。
    select a.field1,b.field2 from a,b where a.field3=b.field3
 1. field3上没有索引的情况下:
    对a作全表扫描,结果排序
    对b作全表扫描,结果排序
    结果合并。
    对于很小的表或巨大的表比较合适。

 2. field3上有索引
    按照表联结的次序,b为驱动表,a为被驱动表
    对b作全表扫描
    对a作索引范围扫描
    如果匹配,通过a的rowid访问

(16) 避免一对多的join。如:
     select tb1.field3,tb1.field4,tb2.field2 from tb1,tb2 where tb1.field2=tb2.field2 and tb1.field2=‘BU1032’ and tb2.field2= ‘aaa’
     不如:
     declare @a varchar(80)
select @a=field2 from tb2 where field2=‘aaa’ 
     select tb1.field3,tb1.field4,@a from tb1 where field2= ‘aaa’

(16) 子查询
    用exists/not exists代替in/not in操作
    比较:
    select a.field1 from a where a.field2 in(select b.field1 from b where b.field2=100)
    select a.field1 from a where exists( select 1 from b where a.field2=b.field1 and b.field2=100)

    select field1 from a where field1 not in( select field2 from b)
    select field1 from a where not exists( select 1 from b where b.field2=a.field1)

(17) 主、外键主要用于数据约束,sybase中创建主键时会自动创建索引,外键与索引无关,提高性能必须再建索引。

(18) char类型的字段不建索引比int类型的字段不建索引更糟糕。建索引后性能只稍差一点。

(19)   使用count(*)而不要使用count(column_name),避免使用count(distinct column_name)。

(20) 等号右边尽量不要使用字段名,如:
select * from tb where field1 = field3
 
(21) 避免使用or条件,因为or不使用索引。

2.避免使用order by和group by字句。
    因为使用这两个子句会占用大量的临时空间(tempspace),如果一定要使用,可用视图、人工生成临时表的方法来代替。
   如果必须使用,先检查memory、tempdb的大小。
   测试证明,特别要避免一个查询里既使用join又使用group by,速度会非常慢!

3.尽量少用子查询,特别是相关子查询。因为这样会导致效率下降。
一个列的标签同时在主查询和where子句中的查询中出现,那么很可能当主查询中的列值改变之后,子查询必须重新查询一次。查询嵌套层次越多,效率越低,因此应当尽量避免子查询。如果子查询不可避免,那么要在子查询中过滤掉尽可能多的行。

 
 
4.消除对大型表行数据的顺序存取
在嵌套查询中,对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存取策略,一个嵌套3层的查询,如果每层都查询1000行,那么这个查询就要查询10亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如,两个表:学生表(学号、姓名、年龄……)和选课表(学号、课程号、成绩)。如果两个表要做连接,就要在“学号”这个连接字段上建立索引。
还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引,但某些形式的where子句强迫优化器使用顺序存取。下面的查询将强迫对orders表执行顺序操作:
SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008
虽然在customer_num和order_num上建有索引,但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合,所以应该改为如下语句:
SELECT * FROM orders WHERE customer_num=104 AND order_num>1001
UNION
SELECT * FROM orders WHERE order_num=1008
这样就能利用索引路径处理查询。
5.避免困难的正规表达式
MATCHES和LIKE关键字支持通配符匹配,技术上叫正规表达式。但这种匹配特别耗费时间。例如:SELECT * FROM customer WHERE zipcode LIKE “98_ _ _”
即使在zipcode字段上建立了索引,在这种情况下也还是采用顺序扫描的方式。如果把语句改为SELECT * FROM customer WHERE zipcode >“98000”,在执行查询时就会利用索引来查询,显然会大大提高速度。
另外,还要避免非开始的子串。例如语句:SELECT * FROM customer WHERE zipcode[2,3] >“80”,在where子句中采用了非开始子串,因而这个语句也不会使用索引。
6.使用临时表加速查询
把表的一个子集进行排序并创建临时表,有时能加速查询。它有助于避免多重排序操作,而且在其他方面还能简化优化器的工作。例如:
SELECT cust.name,rcvbles.balance,……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
AND cust.postcode>“98000”
ORDER BY cust.name
如果这个查询要被执行多次而不止一次,可以把所有未付款的客户找出来放在一个临时文件中,并按客户的名字进行排序:
SELECT cust.name,rcvbles.balance,……other columns
FROM cust,rcvbles
WHERE cust.customer_id = rcvlbes.customer_id
AND rcvblls.balance>0
ORDER BY cust.name
INTO TEMP cust_with_balance
然后以下面的方式在临时表中查询:
SELECT * FROM cust_with_balance
WHERE postcode>“98000”
临时表中的行要比主表中的行少,而且物理顺序就是所要求的顺序,减少了磁盘I/O,所以查询工作量可以得到大幅减少。
注意:临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下,注意不要丢失数据。
7.用排序来取代非顺序存取
非顺序磁盘存取是最慢的操作,表现在磁盘存取臂的来回移动。SQL语句隐藏了这一情况,使得我们在写应用程序时很容易写出要求存取大量非顺序页的查询。
有些时候,用数据库的排序能力来替代非顺序的存取能改进查询。 

2005-9-5 9:10:10   
 查看评语???    

 2005-9-5 10:25:17    关于本文的一些问题以下假设在field1上有唯一索引I1,在field2上有非唯一索引I2。
(3) select field3,field4 from tb where field1='sdf'        快
    select * from tb where field1='sdf'      慢
 因为后者在索引扫描后要多一步ROWID表访问。

 问题:
 为什么后者在索引扫描后多一步ROWID表的访问?
 在我的概念中:
 索引表记录的是 字段值和ROWID,在按某个所有字段查询的时候。
 先在所有表里找到符合条件的ROWID,
 然后再根据ROWID读取表中的数据(就是select 后面跟的n个字段)
 这样的话,其实两个查询都要对ROWID进行访问的呀。
 
 我的想法有什么不对的?请指教?

 select field2,field3,field4 from tb where field1='sdf'
 这个查询要不要对索引扫描后再多一步的ROWID表访问的?

(4) select field3,field4 from tb where field1>='sdf'        快
select field3,field4 from tb where field1>'sdf'        慢
因为前者可以迅速定位索引。

问题:
为什么前者可以迅速定位?呵呵,原来上面是怎么解释的?

(12) 索引值过大(如在一个char(40)的字段上建索引),会造成大量的I/O开销(甚至会超过表扫描的I/O开销)。因此,尽量使用整数索引。 Sp_estspace可以计算表和索引的开销。
问题:
找不到 Sp_estspace 对象,我是在ms sql server 2000上找的。


(16) 避免一对多的join。如:
     select tb1.field3,tb1.field4,tb2.field2 from tb1,tb2 where tb1.field2=tb2.field2 and tb1.field2=‘BU1032’ and tb2.field2= ‘aaa’
     不如:
     declare @a varchar(80)
select @a=field2 from tb2 where field2=‘aaa’ 
     select tb1.field3,tb1.field4,@a from tb1 where field2= ‘aaa’

问题:
     select tb1.field3,tb1.field4,tb2.field2 from tb1,tb2 where tb1.field2=tb2.field2 and tb1.field2=‘BU1032’ and tb2.field2= ‘aaa’
这个结果查处理应该是个空的结果集啊。
我觉得 和下面的这段查询返回的结果集不一定等价
select @a=field2 from tb2 where field2=‘aaa’ 
     select tb1.field3,tb1.field4,@a from tb1 where field2= ‘aaa’

(20) 等号右边尽量不要使用字段名,如:
select * from tb where field1 = field3

问题:
等号右边尽量不要使用字段名? 那 field1,field3  是什么?


(21) 避免使用or条件,因为or不使用索引。

2.避免使用order by和group by字句。
    因为使用这两个子句会占用大量的临时空间(tempspace),如果一定要使用,可用视图、人工生成临时表的方法来代替。
   如果必须使用,先检查memory、tempdb的大小。
   测试证明,特别要避免一个查询里既使用join又使用group by,速度会非常慢!
问题:
可用视图、人工生成临时表的方法来代替。  怎么做啊?
特别要避免一个查询里既使用join又使用group by,速度会非常慢! 假如真的需要做连接还要做分组统计(group),用什么比较好?
还有问一下 select * from tb1,tb2 where tb1.ID=tb2.ID  和 select * from tb1 inner join tb2 on tb1.ID=tb2.ID
哪个执行效率高?

--------------------------------------------------------------------------------


--------------------------------------------------------------------------------

大富翁论坛版权所有
 KeyLife富翁笔记 
作者: fanghongbin
标题: sql转
关键字: sql
分类: 个人专区
密级: 公开
(评分:★★★★★ , 回复: 1, 阅读: 1173) ??
daxia003 (2001-12-17 17:16) 794281
收集SQL语句使用技巧!!!(只要不是太普通的就行了!带条例子语句!)

一条十分!!!

先到先得!!!
GZCYP (2001-12-17 17:21)
SQL没有技巧,只有经验和学习。
SuperJS (2001-12-17 17:30)
给你一条以前在csdn看到的!
  SELECT DISTINCT SUBSTRING( KMM102.KMM102_BGT_TYPE,1,4 ) AS BGT_TYPE,  
         ( CASE SUBSTRING( KMM102.KMM102_BGT_TYPE,3,2 ) WHEN "09" THEN "1" WHEN "10" THEN "2"
                                                        WHEN "11" THEN "3" ELSE "9" END ) AS BGT_CLASS,  
         SUBSTRING( KMM102.KMM102_BGT_TYPE,1,2 ) AS BGT_TEAM,  

         ( ISNULL( (SELECT SUBSTRING(KMC101.KMC101_NAME,CHARINDEX("-",KMC101.KMC101_NAME)+1,12) FROM KMC101 
                     WHERE ( KMC101.KMC101_TYPE = "BUDGETCODE" )
                       AND ( KMC101.KMC101_CODE = SUBSTRING( KMM102.KMM102_BGT_TYPE,1,4 ) + "00" ) ),"" ) ) AS BGT_NAME,  

         SUM( ISNULL( KMM101.KMM101_BGT_JAN,0 ) ) AS BGT_AMT01,  
         SUM( ISNULL( KMM101.KMM101_BGT_FEB,0 ) ) AS BGT_AMT02,  
         SUM( ISNULL( KMM101.KMM101_BGT_MAR,0 ) ) AS BGT_AMT03,  
         SUM( ISNULL( KMM101.KMM101_BGT_APR,0 ) ) AS BGT_AMT04,  
         SUM( ISNULL( KMM101.KMM101_BGT_MAY,0 ) ) AS BGT_AMT05,  
         SUM( ISNULL( KMM101.KMM101_BGT_JUN,0 ) ) AS BGT_AMT06,  
         SUM( ISNULL( KMM101.KMM101_BGT_JUL,0 ) ) AS BGT_AMT07,  
         SUM( ISNULL( KMM101.KMM101_BGT_AUG,0 ) ) AS BGT_AMT08,  
         SUM( ISNULL( KMM101.KMM101_BGT_SEP,0 ) ) AS BGT_AMT09,  
         SUM( ISNULL( KMM101.KMM101_BGT_OCT,0 ) ) AS BGT_AMT10,  
         SUM( ISNULL( KMM101.KMM101_BGT_NOV,0 ) ) AS BGT_AMT11,  
         SUM( ISNULL( KMM101.KMM101_BGT_DEC,0 ) ) AS BGT_AMT12,

         ( SUM( ISNULL( KMM101.KMM101_BGT_JAN,0 ) ) + SUM( ISNULL( KMM101.KMM101_BGT_FEB,0 ) ) +
           SUM( ISNULL( KMM101.KMM101_BGT_MAR,0 ) ) + SUM( ISNULL( KMM101.KMM101_BGT_APR,0 ) ) +
           SUM( ISNULL( KMM101.KMM101_BGT_MAY,0 ) ) + SUM( ISNULL( KMM101.KMM101_BGT_JUN,0 ) ) +
           SUM( ISNULL( KMM101.KMM101_BGT_JUL,0 ) ) + SUM( ISNULL( KMM101.KMM101_BGT_AUG,0 ) ) +
           SUM( ISNULL( KMM101.KMM101_BGT_SEP,0 ) ) + SUM( ISNULL( KMM101.KMM101_BGT_OCT,0 ) ) +
           SUM( ISNULL( KMM101.KMM101_BGT_NOV,0 ) ) + SUM( ISNULL( KMM101.KMM101_BGT_DEC,0 ) ) ) AS AMT01, 
         ( "XXXXXXXX" ) AS AMT02, 

         SUM( ISNULL( ( CASE WHEN ( CONVERT(CHAR(8),KMM102.KMM102_CHK_DATE,112) < "YYYYMMDD" )
                             THEN KMM102.KMM102_CHK_AMT ELSE 0 END ),0 ) ) AS AMT09, 
         SUM( ISNULL( ( CASE WHEN ( ( CONVERT(CHAR(8),KMM102.KMM102_OVER_DATE,112) < "YYYYMMDD" )
                              AND KMM102.KMM102_OVER_STATUS <> "00" )
                             THEN KMM102.KMM102_OVER_AMT
                             WHEN ( ( CONVERT(CHAR(8),KMM102.KMM102_OVER_DATE,112) < "YYYYMMDD" )
                              AND KMM102.KMM102_OVER_STATUS = "00" )
                             THEN KMM102.KMM102_OVER_AMT ELSE 0 END ),0 ) ) AS AMT07, 
         SUM( ISNULL( ( SELECT CASE WHEN ( ( CONVERT(CHAR(8),KMM103.KMM103_PAY_DATE,112) < "YYYYMMDD" )
                                     AND KMM103.KMM103_PAY_STATUS <> "2" )
                                    THEN KMM103.KMM103_PAY_AMT ELSE 0 END
                                    FROM KMM103
                                   WHERE ( KMM103.KMM103_YY = KMM102.KMM102_YY ) 
                                     AND ( KMM103.KMM103_BGT_KIND = KMM102.KMM102_BGT_KIND ) 
                                     AND ( KMM103.KMM103_CASE_NO = KMM102.KMM102_CASE_NO ) ),0 ) ) AS AMT03,  
         SUM( ISNULL( ( SELECT CASE WHEN ( ( CONVERT(CHAR(8),KMM103.KMM103_PAY_DATE,112) < "YYYYMMDD" )
                                     AND KMM103.KMM103_PAY_STATUS <> "1" )
                                    THEN KMM103.KMM103_PAY_AMT ELSE 0 END
                                    FROM KMM103
                                   WHERE ( KMM103.KMM103_YY = KMM102.KMM102_YY ) 
                                     AND ( KMM103.KMM103_BGT_KIND = KMM102.KMM102_BGT_KIND ) 
                                     AND ( KMM103.KMM103_CASE_NO = KMM102.KMM102_CASE_NO ) ),0 ) ) AS AMT04  
    FROM KMM102,  
         KMM101 
   WHERE ( KMM102.KMM102_YY = "YYY" ) AND
         ( KMM102.KMM102_BGT_KIND = "1" ) AND
         ( KMM101.KMM101_YY =* KMM102.KMM102_YY ) AND
         ( KMM101.KMM101_BGT_KIND =* KMM102.KMM102_BGT_KIND ) AND
         ( KMM101.KMM101_BGT_TYPE =* KMM102.KMM102_BGT_TYPE )
GROUP BY SUBSTRING( KMM102.KMM102_BGT_TYPE,1,4 ), 
         SUBSTRING( KMM102.KMM102_BGT_TYPE,3,2 ), 
         SUBSTRING( KMM102.KMM102_BGT_TYPE,1,2 )  
ORDER BY BGT_CLASS ASC,  
         BGT_TYPE DESC 
;
我这条如果只给10分是不是太少了!
大多数用select可能遇到的都遇到了!
bbs_delphi (2001-12-17 17:28)
gz
Zane (2001-12-17 17:29)
具体问题,具体分析
坛子 (2001-12-17 17:33)
Advanced SQL Code Collection v1.2.0  

Powerful editor that enables you to write your SQL scripts efficiently. It includes SQL
syntax highlighting, large base of SQL code templates, power search engine and convenient
bookmarks
风中流云 (2001-12-17 17:52)
agree zane
kals (2001-12-17 19:15)
一条两百分还差不多
sxbing (2001-12-17 23:4)
select * from *
hwchen (2001-12-17 23:20)
select * into #tmp from *
drop #tmp
marknew (2001-12-18 9:6)
select * from *   --》这是什么东东呀?乱讲.
看下我的存贮过程吧,里面还有很多技巧.
CREATE PROCEDURE PickDelta
       @pick_num         char(14),
       @prepare_by       varchar(20),
       @lcInitShipMaxNo  varchar(20),
       @lcInitSalesMaxNo varchar(20),
       @ship_date        datetime,
       @GenNewSales      varchar(200)='' output,
       @GenNewShips      varchar(200)='' output,
       @Have_ship        boolean=0 output      
AS
declare @affect_row integer,@temp_store_qty  integer
declare @DtempSeq_no tinyint,@Dtempproduct_code char(10),@Dtempvdr_id char(4),@Dtempstore_id char(6),@Dtempship_qty int
declare @i tinyint,@err_msg varchar(200),@Err_salesTitle varchar(100),@Have_LessSale  bit
declare @c_id char(8),@tran_ltd varchar(80),@rec_acc_status char(1)
declare @TempStr varchar(20)
select  @affect_row=0
select  @Have_ship=0
select  @i=0
SET NOCOUNT ON
if exists (select * from tempdb.dbo.sysobjects where name ="##temp_store")
begin
         drop table ##temp_store
end
--得到本张检货单用到的所有的配件的库存临时表##temp_store
select * into ##temp_store from info_part_store where product_code+vdr_id+store_id in (select product_code+vdr_id+store_id
                                                                 from pick_detail where pick_num=@pick_num)
if @@rowcount<=0
begin
   raiserror('在库存中没有找到任何配件,请确认这张捡货单是否有效',16,1)
   return
end
begin transaction  
--定义所有客户游标cursor_client
select cursor_status('local','cursor_client')
if cursor_status('local','cursor_client')>0
begin
   CLOSE cursor_client
   DEALLOCATE cursor_client
end
declare cursor_client Cursor local For
        select distinct a.c_id,isnull(b.tran_ltd,'') as tran_ltd,isnull(b.rec_acc_status,'') as rec_acc_status
                        from pick_detail a left join sales_title b on b.sales_no=a.sales_no where a.pick_num=@pick_num
Open cursor_client
-- 取出一个客户
Fetch Next From cursor_client into   @c_id,@tran_ltd,@rec_acc_status
While @@Fetch_Status=0
begin
   --依据每个不同的客户生成新的出库单 
   if exists (select * from tempdb.dbo.sysobjects where name ="##temp_pick")
   begin
         drop table ##temp_pick
   end
   --生成临时表的序号无论库存够与否都要生成出库单,如果所有对应的库存都是0或者没有找到对应的库位则不生成
   select a.pick_num,a.seq_no into ##temp_pick from pick_detail a 
        left join info_part_store b on b.product_code=a.product_code and b.store_id=a.store_id and b.vdr_id=a.vdr_id
        where pick_num=@pick_num and a.c_id=@c_id  and a.ship_qty>0 and b.store_qty>0
   --如果有数据可以生成出库单的话
   if @@rowcount>0
   begin           
      select @Have_Ship=1      --有数据可以生成出库单
      --定义当前客户的临时游标
     if cursor_status('local','cursor_pick_detail')>0
     begin
          CLOSE cursor_pick_detail
          DEALLOCATE cursor_pick_detail
     end
      Declare cursor_pick_detail Cursor local For
             select seq_no,product_code,vdr_id,store_id,ship_qty from pick_detail where pick_num=@pick_num and c_id=@c_id
                                                                      order by product_code,vdr_id,store_id
      Open cursor_pick_detail
      --取出每一行的检货值
      Fetch Next From cursor_pick_detail  into  @DtempSeq_no,@Dtempproduct_code,@Dtempvdr_id,@Dtempstore_id,@Dtempship_qty
      While @@Fetch_Status=0
      begin
         --得到对应的库存数量
         select @temp_store_qty=(select top 1 store_qty from ##temp_store
                                where product_code=@DtempProduct_code and vdr_id=@Dtempvdr_id and store_id=@Dtempstore_id)
         --库存数量不为空
         if @temp_store_qty is not null and @temp_store_qty>0
         begin
            --生成出库单明细资料         
             select @i=@i+1
             insert ship_detail select @lcInitShipMaxNo,@i,a.product_code,a.vdr_id,a.vdr_short,a.chinese_name,
                 a.meter_unit,a.model_no,
                 case
                        when a.ship_qty>@temp_store_qty then @temp_store_qty
                                                        else a.ship_qty
                 end,
                 b.ref_sale_price,a.store_id,0,
                  '检货单号:'+a.pick_num+'行号:'+convert(varchar(10),a.seq_no) from  pick_detail a
                 left join info_moto_part  b on b.product_code=a.product_code     
                 where  a.pick_num=@pick_num and a.seq_no=@DtempSeq_No
                 if @@error<>0
                 begin
                     select @Err_msg="生成的出库单"+@lcInitShipMaxNo+"明细时出错"
                     raiserror(@Err_msg,16,1)
                     rollback transaction
                  end         
 
                 --修改对应订单的完成数量           
                 update sales_detail set cmp_qty=
                            case  
                             when b.ship_qty>@temp_store_qty then @temp_store_qty
                                                                else b.ship_qty
                             end
                             from sales_detail a,pick_detail b where b.sales_no=a.sales_no and b.sales_seq_no=a.seq_no                
        end--处理当前客户每一行的捡货数量
        Fetch Next From cursor_pick_detail into  @DtempSeq_no,@Dtempproduct_code,@Dtempvdr_id,@Dtempstore_id,@Dtempship_qty
     end--得到当前客户下一行的捡货数据
     --生成出库单标题资料            
     if @Have_Ship=1
      begin
         --定义所有订单号游标cursor_sales        
         declare @AllSalesNo varchar(300)
         declare @DtempSalesNo varchar(20)
         select  @AllSalesNo=''
         if cursor_status('local','cursor_sales')>0
         begin
            CLOSE cursor_sales 
            DEALLOCATE cursor_sales 
          end
         declare cursor_sales   Cursor local For       
                   select distinct sales_no from pick_detail where pick_num=@pick_num
         open cursor_sales
         Fetch Next From cursor_sales  into  @DtempSalesNo
         While @@Fetch_Status=0
         begin
            if @AllSalesNo=''
               select  @AllSalesNo= "'"+@DtempSalesNo+"'"
            else
               select  @AllSalesNo= "'"+@AllSalesNo+"',"+@DtempSalesNo
            Fetch Next From cursor_sales  into  @DtempSalesNo
         end
         CLOSE cursor_sales 
         DEALLOCATE cursor_sales 
         insert into ship_title(flow_num,ship_num,ship_date,c_id,tran_ltd,ship_type_id,rec_acc_status,ship_status,prepare_by,remark,sales_no)
                    values(@pick_num,@lcInitShipMaxNo,@ship_Date,@c_id,@tran_ltd,'00',@rec_acc_status,'未审',@prepare_by,'检货单号:'+@pick_num,@AllSalesNo)
         if @@error<>0
         begin
               select @Err_msg="生成的出库单"+@lcInitShipMaxNo+"标题时出错"
               raiserror(@Err_msg,16,1)
               rollback transaction
        end
        select @GenNewShips=@GenNewShips+char(13)+@lcInitShipMaxNo
        select @TempStr=substring(@lcInitShipMaxNo,1,8)
        select @lcInitShipMaxNo=convert(int,substring(@lcInitShipMaxNo,9,4))+1
        select @lcInitShipMaxNo=@TempStr+replicate("0",4-len(convert(varchar(10),@lcInitShipMaxNo)))+convert(char(4),@lcInitShipMaxNo)
      end
      end --处理当前客户的捡货出库情况
      --依据每个不同的客户生成新的缺货订单
      if exists (select * from tempdb.dbo.sysobjects where name ="##temp_sales")
      begin
         drop table ##temp_sales
      end              
      select @lcInitSalesMaxNo as sales_no,IDENTITY(int,1,1) as seq_no,a.product_code,a.vdr_id,a.vdr_short,a.chinese_name,a.meter_unit,a.model_no,
           abs(isnull(b.store_qty,0)-sum(ship_qty)) as sales_qty,0 as cmp_qty,'缺货检货单;'+a.pick_num as remark into ##temp_sales from pick_detail a
           left join ##temp_store b on b.product_code=a.product_code and b.vdr_id=a.vdr_id and b.store_id=a.store_id
           where a.pick_num=@pick_num and c_id=@c_id group by a.product_code,a.chinese_name,a.meter_unit,a.model_no,a.vdr_id,
           a.vdr_short,b.store_qty,a.pick_num having isnull(b.store_qty,0)-sum(a.ship_qty)<0
           if @@rowcount>0
           begin
               select  @Have_LessSale=1
               insert  sales_detail select * from ##temp_sales
               if @@error<>0
                  begin
                     select @Err_salesTitle ="生成缺货订单的标题"+@lcInitSalesMaxNo+"出错"
                     raiserror(@Err_salesTitle,16,1)
                     rollback transaction
                  end
               insert  into sales_title(sales_no,c_id,c_short,sales_date,ship_type_id,po_status,remark) select
                       @lcInitSalesMaxNo,@c_id,c_short,getdate(),'00','未完','由检货单'+@pick_num+'生成' from info_client where c_id=@c_id
               if @@error<>0
                   begin
                       select @Err_salesTitle ="生成缺货订单的明细"+@lcInitSalesMaxNo+"出错"
                       raiserror(@Err_salesTitle,16,1)
                       rollback transaction
                   end
       
               select @GenNewSales=@GenNewSales+char(13)+@lcInitSalesMaxNo
              
               select @TempStr=substring(@lcInitSalesMaxNo,1,8)
               select @lcInitSalesMaxNo=convert(int,substring(@lcInitSalesMaxNo,9,4))+1
               select @lcInitSalesMaxNo=@TempStr+replicate("0",4-len(convert(varchar(10),@lcInitSalesMaxNo)))+convert(char(4),@lcInitSalesMaxNo)
               select @lcInitSalesMaxNo
           end
            --依据每个不同的客户生成新的缺货订单
           
            --修改临时表的对应的配件的库存数量
            update ##temp_store set store_qty=
                   case
                        when isnull(b.ship_qty,0)>store_qty then 0
                                                            else store_qty-isnull(b.ship_qty,0)
                        end
            from ##temp_store a
            left join pick_detail b on b.product_code=a.product_code and b.vdr_id=a.vdr_id and b.store_id=a.store_id 
                                    and b.pick_num=@pick_num and b.c_id=@c_id          
   Fetch Next From cursor_client into  @c_id,@tran_ltd,@rec_acc_status
end-- 处理下一个客户
 --修改实际库存数量
update info_part_store set store_qty=isnull(b.store_qty,0)
       from  info_part_store a,##temp_store b
       where b.product_code=a.product_code and b.vdr_id=a.vdr_id and b.store_id=a.store_id      
--修改相应的订单状态
Update sales_title set po_status="出库" where sales_no in
                   (select distinct sales_no from pick_detail where pick_num=@pick_num)
--修改检货单状态
update pick_title set pick_status="审核" where pick_num=@pick_num
if cursor_status('local','cursor_client')>0
begin
   CLOSE cursor_client
   DEALLOCATE cursor_client
end
if cursor_status('local','cursor_pick_detail')>0
begin
   CLOSE cursor_pick_detail
   DEALLOCATE cursor_pick_detail
end
commit transaction
浩毛 (2001-12-18 9:18)
太多了
if exists (select * from dbo.sysobjects where id = object_id('jltmp_单位基本情况表'))
  drop table dbo.jltmp_单位基本情况表
if exists (select * from dbo.sysobjects where id = object_id('jltmp_单位基本情况表2'))
  drop table dbo.jltmp_单位基本情况表2
if exists (select * from dbo.sysobjects where id = object_id('jltmp_系统单位类别字典表'))
  drop table dbo.jltmp_系统单位类别字典表
if exists (select * from dbo.sysobjects where id = object_id('jltmp_系统经济性质字典表'))
  drop table dbo.jltmp_系统经济性质字典表
if exists (select * from dbo.sysobjects where id = object_id('jltmp_系统片区字典表'))
  drop table dbo.jltmp_系统片区字典表
if exists (select * from dbo.sysobjects where id = object_id('jltmp_IncreNumber'))
  drop function dbo.jltmp_IncreNumber
if exists (select * from dbo.sysobjects where id = object_id('jltmp_整理数据'))
  drop procedure dbo.jltmp_整理数据
if exists (select * from dbo.sysobjects where id = object_id('jltmp_整理数据2'))
  drop procedure dbo.jltmp_整理数据2
if exists (select * from dbo.sysobjects where id = object_id('jltmp_添加数据'))
  drop procedure dbo.jltmp_添加数据
if exists (select * from dbo.sysobjects where id = object_id('dbo.jltmp_许可证编号转换'))
drop function dbo.jltmp_许可证编号转换
GO

create function dbo.jltmp_许可证编号转换
(
  @psNumber varchar(100),
  @len int
)
RETURNS varchar(100) AS
BEGIN
declare @sNewNumber varchar(100),
        @iPos int
 if @psNumber is null select @sNewNumber=null --返回null
  else
  begin
    select @psNumber=ltrim(rtrim(@psNumber))
    select @iPos=len(@psNumber)
    --小于等于10为的许可证编码不变
if @iPos=0 select @sNewNumber=null --空格返回null
else begin
     if @iPos<=10 select @sNewNumber=@psNumber
     else begin
select @sNewNumber=substring(@psNumber,(@len+1),(@iPos-@len))
if len(ltrim(rtrim(@sNewNumber)))<>@iPos-@len select @sNewNumber=null
     end
end
  end
  return @sNewNumber
END
GO

create table dbo.jltmp_单位基本情况表
(
  申请编号 varchar(40) null,
  单位名称 varchar(100) null,
  单位类别 varchar(60) null,
  经济性质 varchar(60) null,
  地址 varchar(100) null,
  电话 varchar(60) null,
  法人或法人代表 varchar(60) null,
 -- 负责人 varchar(60) null,
  经营范围 varchar(80) null,
  主管部门 varchar(60) null,
  职工人数 int null,
  从业人员数 int null,
  建档日期 datetime null,
  卫生许可证号 varchar(60) null,
  卫生卡号 varchar(60) null,
  片区 varchar(60) null,
  操作日期 datetime null,
  状态 varchar(60) null,
  年度评价 varchar(255) null,
  应体检日期 datetime null,
  下次定期监测日期 datetime null,
  档案编号 varchar(60) null,
  卫生种类 varchar(60) null,
  助记符 varchar(60) null,
  有效开始日期 datetime null,
  有效截止日期 datetime null,
  最后复验日期 datetime null
)

create table dbo.jltmp_单位基本情况表2
(
申请编号 UDT_申请编号 not null,
档案编号 UDT_档案编号 not null,
单位名称 varchar(80) null,
法人代表 varchar(20) null,
经济性质 varchar(20) null,
片区 varchar(20) null,
地址 varchar(80) null,
街道 varchar(20) null,
电话 varchar(20) null,
职工人数 int null,
从业人数 int null,
卫生种类 varchar(10) null,
行业类别 varchar(40) null,
经营内容 varchar(80) null,
主管单位 varchar(60) null,
应体检人数 int null,
已体检人数 int null,
卫生许可证号 char(10) null,
助记符 varchar(40) null,
建档日期 datetime not null,
有效开始日期 datetime null,
有效截止日期 datetime null,
最后复验日期 datetime null
)


create table dbo.jltmp_系统单位类别字典表
(
  编号 varchar(20) null,
  内容 varchar(60) null,
  卫生种类 varchar(20) null
)
create table dbo.jltmp_系统经济性质字典表
(
  编号 varchar(20) null,
  内容 varchar(60) null
)
create table dbo.jltmp_系统片区字典表
(
  编号 varchar(20) null,
  内容 varchar(60) null
)
GO


create function dbo.jltmp_IncreNumber
(
  @psNumber varchar(100)
)
RETURNS varchar(100) AS
BEGIN

  declare @sNewNumber varchar(100),@iPos int

  if @psNumber is null select @sNewNumber='01'
  else begin
    select @iPos=len(@psNumber)
    while @iPos>0 and substring(@psNumber,@iPos,1)>='0' and substring(@psNumber,@iPos,1)<='9'
      select @iPos=@iPos - 1
    if @iPos>0 begin
      select @sNewNumber=substring(@psNumber,1,@iPos)
      select @psNumber=substring(@psNumber,@iPos+1,len(@psNumber) - @iPos) end
    else select @sNewNumber=''
    select @iPos=len(@psNumber)
    select @psNumber=rtrim(ltrim(str(convert(int, @psNumber)+1)))
    -- @iPos may < len(@psNumber), for example, @psNumber = '9' + 1 -> '10'
    --because replace(' ',space(<=0), '0')=' ', so
    if @iPos<=len(@psNumber) select @sNewNumber=@sNewNumber+@psNumber
    else select @sNewNumber=@sNewNumber+replace(space(@iPos -len(@psNumber)),' ', '0')+@psNumber
  end
  return @sNewNumber
END
GO

create procedure dbo.jltmp_整理数据2 as
BEGIN
set nocount on

  --添加字典数据
  delete jltmp_系统单位类别字典表
  insert into jltmp_系统单位类别字典表 select distinct null,单位类别,卫生种类 from jltmp_单位基本情况表 where 单位类别 is not null
  delete jltmp_系统片区字典表
  insert into jltmp_系统片区字典表 select distinct null,片区 from jltmp_单位基本情况表 where 片区 is not null
  delete jltmp_系统经济性质字典表
  insert into jltmp_系统经济性质字典表 select distinct null,经济性质 from jltmp_单位基本情况表 where 经济性质 is not null

  --经济性质升级与防疫26一致
  update jltmp_单位基本情况表 set 经济性质 = case
      when 经济性质 in ('国有','集体','私营') then 经济性质 + '企业'
      when 经济性质 = '股份制' then '股份企业'
      else 经济性质
    end
  update jltmp_系统经济性质字典表 set 内容 = case
      when 内容 in ('国有','集体','私营') then 内容 + '企业'
      when 内容 = '股份制' then '股份企业'
      else 内容
    end
  --升级单位类别
  update jltmp_单位基本情况表
set 单位类别 = case
when 单位类别 ='糕点 蜜饯' then '糕点,蜜饯'
else replace(单位类别,' ','')
  end
  update jltmp_系统单位类别字典表
set 内容 = case
when 内容 = '糕点 蜜饯' then '糕点,蜜饯'
        else replace(内容,' ','')
  end

--select distinct 单位类别 from jltmp_单位基本情况表
END
GO


create procedure dbo.jltmp_整理数据 as
BEGIN
set nocount on
  --删除重复单位
  delete jltmp_单位基本情况表 from jltmp_单位基本情况表 a,单位档案_单位基本信息表 b
    where a.单位名称=b.单位名称 and a.片区=b.片区 and a.卫生种类=b.卫生种类 and a.经济性质=b.经济性质 and a.单位类别=b.行业类别

  --删除已存在的单位类别
  delete jltmp_系统单位类别字典表 from jltmp_系统单位类别字典表 a,系统管理_字典_字典内容表 b
    where a.内容=b.名称 and b.ID=dbo.系统管理_获取字典类别ID('行业属性字典') and
          b.Parent = (select InnerID from 系统管理_字典_字典内容表
                       where ID=dbo.系统管理_获取字典类别ID('行业属性字典') and
                             名称=a.卫生种类 and Parent=0)
  --删除已存在的片区
  delete jltmp_系统片区字典表 from jltmp_系统片区字典表 a,系统管理_字典_字典内容表 b
    where a.内容=b.名称 and b.ID=dbo.系统管理_获取字典类别ID('片区街道字典') and Parent=0
  --删除已存在的经济性质
  delete jltmp_系统经济性质字典表 from jltmp_系统经济性质字典表 a,系统管理_字典_字典内容表 b
    where a.内容=b.名称 and b.ID=dbo.系统管理_获取字典类别ID('经济性质字典') and Parent=0

  --处理片区为null的单位
  if exists (select * from jltmp_单位基本情况表 where 片区 is null)
  begin
    update jltmp_单位基本情况表
set 片区 ='<未定>'
where 片区 is null
    insert into jltmp_系统片区字典表 values(null,'<未定>')
  end
    --处理经济性质为null的单位
  if exists (select * from jltmp_单位基本情况表 where 经济性质 is null)
  begin
    update jltmp_单位基本情况表
set 经济性质 ='<未定>'
where 经济性质 is null
    insert into jltmp_系统经济性质字典表 values(null,'<未定>')
  end
  --处理建档日期为null的单位,更改为当前日期
  if exists (select * from jltmp_单位基本情况表 where 建档日期 is null)
  begin
  update jltmp_单位基本情况表
set 建档日期=getdate()
where 建档日期 is null
  end
 
END
GO

create procedure dbo.jltmp_添加数据 as
BEGIN
set nocount on
declare
  @申请编号 varchar(40),@单位名称 varchar(100),@单位类别 varchar(60),@经济性质 varchar(60),
  @地址 varchar(100),@电话 varchar(60),@法人或法人代表 varchar(60),@负责人 varchar(60),
  @经营范围 varchar(60),@主管部门 varchar(60),@职工人数 int,@从业人员数 int,
  @建档日期 datetime,@卫生许可证号 varchar(60),@片区 varchar(60),@档案编号 varchar(60),
  @卫生种类 varchar(60),@助记符 varchar(60),@编号 varchar(60),@内容 varchar(60),
  @ID varchar(20),@InnerID int,
  @有效开始日期 datetime,
  @有效截止日期 datetime,
  @最后复验日期 datetime

--逐个添加经济性质
declare cur经济性质 cursor for select distinct 内容 from jltmp_系统经济性质字典表
open cur经济性质
fetch cur经济性质 into @内容
select @ID=dbo.系统管理_获取字典类别ID('经济性质字典')
select @编号=isnull(max(编号),'00') from 系统管理_字典_字典内容表 where ID=@ID
while @@fetch_status=0 begin
  select @编号=dbo.jltmp_IncreNumber(@编号)
  insert into 系统管理_字典_字典内容表 values(@ID,@编号,@内容,'','<防疫25升级到26单位档案导入>',0)
  fetch cur经济性质 into @内容
end
deallocate cur经济性质
--逐个添加片区
declare cur片区 cursor for select distinct 内容 from jltmp_系统片区字典表
open cur片区
fetch cur片区 into @内容
select @ID=dbo.系统管理_获取字典类别ID('片区街道字典')
select @编号=isnull(max(编号),'00') from 系统管理_字典_字典内容表 where ID=@ID
while @@fetch_status=0 begin
  select @编号=dbo.jltmp_IncreNumber(@编号)
  insert into 系统管理_字典_字典内容表 values(@ID,@编号,@内容,'','<防疫25升级到26单位档案导入>',0)
  select @InnerID=max(InnerID) from 系统管理_字典_字典内容表
  insert into 系统管理_字典_字典内容表 values(@ID,@编号+'01','<未定>','','<防疫25升级到26单位档案导入>',@InnerID)
  fetch cur片区 into @内容
end
deallocate cur片区

--逐个添加单位类别
declare cur单位类别 cursor for select distinct 内容,卫生种类 from jltmp_系统单位类别字典表
open cur单位类别
fetch cur单位类别 into @内容,@卫生种类
select @ID=dbo.系统管理_获取字典类别ID('行业属性字典')
while @@fetch_status=0 begin
  select @InnerID=InnerID from 系统管理_字典_字典内容表
   where ID=@ID and 名称=@卫生种类 and Parent=0
  select @编号=dbo.jltmp_IncreNumber(isnull(max(b.编号),max(a.编号)+'00'))
    from 系统管理_字典_字典内容表 a left join 系统管理_字典_字典内容表 b on b.Parent = a.InnerID
   where a.ID=@ID and a.名称=@卫生种类 and a.Parent=0
  insert into 系统管理_字典_字典内容表 values(@ID,@编号,@内容,'','<防疫25升级到26单位档案导入>',@InnerID)
  select @InnerID=max(InnerID) from 系统管理_字典_字典内容表
  insert into 系统管理_字典_字典内容表 values(@ID,@编号+'0','单位类别','','<防疫25升级到26单位档案导入>',@InnerID)
  insert into 系统管理_字典_字典内容表 values(@ID,@编号+'1','经营形式','','<防疫25升级到26单位档案导入>',@InnerID)
  insert into 系统管理_字典_字典内容表 values(@ID,@编号+'2','许可项目','','<防疫25升级到26单位档案导入>',@InnerID)
  fetch cur单位类别 into @内容,@卫生种类
end
deallocate cur单位类别

--逐个添加单位信息
declare cur单位基本情况表 cursor for
  select distinct 单位名称,单位类别,经济性质,地址,电话,法人或法人代表,经营范围,主管部门,建档日期,
           职工人数,从业人员数,卫生许可证号,片区,卫生种类,助记符,有效开始日期,有效截止日期,最后复验日期
    from jltmp_单位基本情况表
open cur单位基本情况表
fetch cur单位基本情况表 into @单位名称,@单位类别,@经济性质,@地址,@电话,@法人或法人代表,@经营范围,@主管部门,
  @建档日期,@职工人数,@从业人员数,@卫生许可证号,@片区,@卫生种类,@助记符,@有效开始日期,@有效截止日期,@最后复验日期
while @@fetch_status=0 begin

  exec 系统管理_返回编号流水号 '单位档案管理','申请编号',@申请编号 output,Null

  select @编号=编号 from 系统管理_字典_字典内容表 a,系统管理_字典_字典表列表 b
   where a.ID=b.ID and b.名称='行业属性字典' and a.名称=@卫生种类

  --以下暂时用 @编号 存储卫生种类的ID
  --参考存储过程 单位档案_生成档案编号
  declare @代号 char(5)
  declare @编号类型 varchar(10)
  if exists(select * from dbo.单位档案_档案编号使用情况表 where substring(档案编号,1,1) = @编号)
  begin
    select @档案编号 =min(CONVERT(int,档案编号)) from dbo.单位档案_档案编号使用情况表
      with (holdlock)
     where substring(档案编号,1,1) = @编号
    delete from dbo.单位档案_档案编号使用情况表 where 档案编号 = @档案编号
  end
  else
  begin
    set @编号类型='档案编号' + @编号
    exec 系统管理_返回编号流水号 '单位档案管理',@编号类型,@代号 output,null
    set @档案编号 = @编号 + @代号
  end

  insert into jltmp_单位基本情况表2(单位名称,行业类别,经济性质,地址,电话,法人代表,经营内容,主管单位,
    建档日期,职工人数,从业人数,卫生许可证号,片区,卫生种类,街道,申请编号,档案编号,助记符,应体检人数,已体检人数,有效开始日期,有效截止日期,最后复验日期)
   values(@单位名称,@单位类别,@经济性质,@地址,@电话,@法人或法人代表,@经营范围,@主管部门,
    @建档日期,@职工人数,@从业人员数,@卫生许可证号,@片区,@卫生种类,'<未定>',@申请编号,@档案编号,@助记符,0,0,@有效开始日期,@有效截止日期,@最后复验日期)   

  fetch cur单位基本情况表 into @单位名称,@单位类别,@经济性质,@地址,@电话,@法人或法人代表,@经营范围,@主管部门,
    @建档日期,@职工人数,@从业人员数,@卫生许可证号,@片区,@卫生种类,@助记符,@有效开始日期,@有效截止日期,@最后复验日期
end
deallocate cur单位基本情况表

  insert into 单位档案_单位基本信息表
(单位名称,行业类别,经济性质,地址,电话,法人代表,经营内容,主管单位,
    建档日期,职工人数,从业人数,卫生许可证号,片区,卫生种类,街道,申请编号,档案编号,助记符,应体检人数,已体检人数)
  select 单位名称,行业类别,经济性质,地址,电话,法人代表,经营内容,主管单位,
    建档日期,职工人数,从业人数,卫生许可证号,片区,卫生种类,街道,申请编号,档案编号,助记符,应体检人数,已体检人数
  from jltmp_单位基本情况表2


END

--delete dbo.单位档案_单位基本信息表
--delete dbo.许可证_使用信息表
--select a.申请编号,a.单位名称,a.卫生许可证号,a.卫生种类,a.建档日期,a.有效截止日期,a.有效开始日期,a.最后复验日期 from jltmp_单位基本情况表2 a where isnull(a.卫生许可证号,'')<>'' and a.申请编号 not in (select b.申请编号 from 许可证_使用信息表 b)
--select * from dbo.单位档案_单位基本信息表
--select * from dbo.jltmp_单位基本情况表2
浩毛 (2001-12-18 9:20)
还有,嘻嘻

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
CREATE    PROCEDURE 检验管理_自动评价
@p收检编号 VARCHAR ( 20 ) = '2001073101100003'
AS

set nocount on
declare @l返回值   varchar(2000),
@l单一样品评价 varchar(500),
@l样品数 int,
@l合格数 int, /*某一样品检验为合格的项目数*/
@l不合格数 int, /*某一样品检验为不合格的项目数*/
@l检验项目数   int, /*记录某单一样品的检验项目数*/
@li  int,  /*用于控制循环次数的变量*/
@lj  int,  /*用于控制循环次数的变量*/
    @l检验结论 varchar(20)

/*建临时表并添入数据,用于记录本次收检的所有样品和每一样品的检验依据,检验结论。*/
select IDENTITY(int) as ID,a.样品名称,a.检验依据,a.检验结论,a.收检编号,a.样品系统编号
into #样品检验信息表
from 检验管理_收检样品信息表 a
where @p收检编号 = 收检编号

/*建临时表,用于记录样品的所有检验项目的检验结果信息.*/
create table #检验项目记录表(ID int IDENTITY,
收检编号 varchar(20),
样品系统编号 varchar(20),
项目名称 varchar(50),
单项结论 varchar(10))

select @li = 1, @l样品数 = max(ID),@l返回值 = '' from #样品检验信息表

while(@li <= @l样品数)
begin
truncate table #检验项目记录表

/*取出并记录下当前样品的检验项目及其结论*/
insert into #检验项目记录表(收检编号,样品系统编号,项目名称,单项结论)
select a.收检编号,a.样品系统编号,c.名称 as 项目名称,a.单项结论
from 检验管理_样品检验项目结果表 a,#样品检验信息表 b,系统管理_检验项目字典视图 c
where a.收检编号 = b.收检编号 and
a.样品系统编号 = b.样品系统编号 and
a.检验项目编号 = c.编号 and
b.ID = @li
order by a.单项结论

select @lj = 1,
@l检验项目数 = max(ID)
from #检验项目记录表

/*检查是否所有的项目都已检验完成(已下检验结论)*/
set @l合格数 = (select count(*) from #检验项目记录表 where 单项结论 = '合格')
set @l不合格数 = (select count(*) from #检验项目记录表 where 单项结论 = '不合格')
if (@l合格数 + @l不合格数 != @l检验项目数)
begin
-- RAISERROR('检验还没完成,不能自动评价',16,1)
-- return -1
set @l合格数 = @l检验项目数 - @l不合格数
end

/*拼自动评价字串*/
select @l单一样品评价 = '依据“' + 检验依据  + '”(标准、规范),' + 样品名称 + '经检测,其中所检 '
from #样品检验信息表 where ID = @li

while(@lj <= @l合格数)  /*拼出合格的检验项目*/
begin
set @l单一样品评价 =ltrim(rtrim( @l单一样品评价)) + (select 项目名称 from #检验项目记录表 where @lj = ID)
  + ','

set @lj = @lj + 1
end

if(@l合格数 > 0)
set @l单一样品评价 = left(@l单一样品评价,len(@l单一样品评价) - 1) + '等项符合标准,'

while(@lj <= @l检验项目数)   /*拼出不合格的检验项目*/
begin
set @l单一样品评价 = @l单一样品评价 + (select 项目名称 from #检验项目记录表 where @lj = ID)
 + convert(varchar(4),@lj) + ','

set @lj = @lj + 1
end

if(@l不合格数 > 0)
set @l单一样品评价 = left(@l单一样品评价,len(@l单一样品评价) - 1) + '等几项不符合标准,'

/*征对一个样品的所有检验项目下一个评价*/
set @l检验结论 = isnull((select 检验结论 from #样品检验信息表 where @li = ID),'合格')

if len(ltrim(@l检验结论)) = 0
set @l检验结论 = '合格'
set @l单一样品评价 = @l单一样品评价 + '判为' + @l检验结论
 + '。' + char(13) + char(10)

set @l返回值 = @l返回值 + @l单一样品评价

set @li = @li + 1
end

/*删除用过的监时表*/

select @l返回值 as 检验评价


GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
zs (2001-12-18 9:30)
gz
cfx (2001-12-19 19:14)
ASC,min,max,
sunstring ,getdate, 还有好多的东西,
最好去搞本SQL
书去看看里面一般都有的
//
保存 评价 游戏规则 免费注册  资料下载 关于本站 


--------------------------------------------------------------------------------

大富翁论坛版权所有
 KeyLife富翁笔记 
作者: f_anny
标题: SQL中日期的处理
关键字: 日期的处理
分类: 个人专区
密级: 公开
(评分: , 回复: 0, 阅读: 114) ??
通常,你需要获得当前日期和计算一些其他的日期,例如,你的程序可能需要判断一个月的第一天或者最后一天。你们大部分人大概都知道怎样把日期进行分割(年、月、日等),然后仅仅用分割出来的年、月、日等放在几个函数中计算出自己所需要的日期!在这篇文章里,我将告诉你如何使用DATEADD和DATEDIFF函数来计算出在你的程序中可能你要用到的一些不同日期。  
      在使用本文中的例子之前,你必须注意以下的问题。大部分可能不是所有例子在不同的机器上执行的结果可能不一样,这完全由哪一天是一个星期的第一天这个设置决定。第一天(DATEFIRST)设定决定了你的系统使用哪一天作为一周的第一天。所有以下的例子都是以星期天作为一周的第一天来建立,也就是第一天设置为7。假如你的第一天设置不一样,你可能需要调整这些例子,使它和不同的第一天设置相符合。你可以通过@@DATEFIRST函数来检查第一天设置。  

      为了理解这些例子,我们先复习一下DATEDIFF和DATEADD函数。DATEDIFF函数计算两个日期之间的小时、天、周、月、年等时间间隔总数。DATEADD函数计算一个日期通过给时间间隔加减来获得一个新的日期。要了解更多的DATEDIFF和DATEADD函数以及时间间隔可以阅读微软联机帮助。  

      使用DATEDIFF和DATEADD函数来计算日期,和本来从当前日期转换到你需要的日期的考虑方法有点不同。你必须从时间间隔这个方面来考虑。比如,从当前日期到你要得到的日期之间有多少时间间隔,或者,从今天到某一天(比如1900-1-1)之间有多少时间间隔,等等。理解怎样着眼于时间间隔有助于你轻松的理解我的不同的日期计算例子。  

一个月的第一天  

      第一个例子,我将告诉你如何从当前日期去这个月的最后一天。请注意:这个例子以及这篇文章中的其他例子都将只使用DATEDIFF和DATEADD函数来计算我们想要的日期。每一个例子都将通过计算但前的时间间隔,然后进行加减来得到想要计算的日期。  

      这是计算一个月第一天的SQL  脚本:  
      SELECT  DATEADD(mm,  DATEDIFF(mm,0,getdate()),  0)  

      我们把这个语句分开来看看它是如何工作的。最核心的函数是getdate(),大部分人都知道这个是返回当前的日期和时间的函数。下一个执行的函数DATEDIFF(mm,0,getdate())是计算当前日期和“1900-01-01  00:00:00.000”这个日期之间的月数。记住:时期和时间变量和毫秒一样是从“1900-01-01  00:00:00.000”开始计算的。这就是为什么你可以在DATEDIFF函数中指定第一个时间表达式为“0”。下一个函数是DATEADD,增加当前日期到“1900-01-01”的月数。通过增加预定义的日期“1900-01-01”和当前日期的月数,我们可以获得这个月的第一天。另外,计算出来的日期的时间部分将会是“00:00:00.000”。  

      这个计算的技巧是先计算当前日期到“1900-01-01”的时间间隔数,然后把它加到“1900-01-01”上来获得特殊的日期,这个技巧可以用来计算很多不同的日期。下一个例子也是用这个技巧从当前日期来产生不同的日期。  

  
本周的星期一  

      这里我是用周(wk)的时间间隔来计算哪一天是本周的星期一。  

      SELECT  DATEADD(wk,  DATEDIFF(wk,0,getdate()),  0)  

一年的第一天  

      现在用年(yy)的时间间隔来显示这一年的第一天。  

      SELECT  DATEADD(yy,  DATEDIFF(yy,0,getdate()),  0)  

季度的第一天  

      假如你要计算这个季度的第一天,这个例子告诉你该如何做。  

      SELECT  DATEADD(qq,  DATEDIFF(qq,0,getdate()),  0)  

当天的半夜  

      曾经需要通过getdate()函数为了返回时间值截掉时间部分,就会考虑到当前日期是不是在半夜。假如这样,这个例子使用DATEDIFF和DATEADD函数来获得半夜的时间点。  

      SELECT  DATEADD(dd,  DATEDIFF(dd,0,getdate()),  0)  

深入DATEDIFF和DATEADD函数计算  

      你可以明白,通过使用简单的DATEDIFF和DATEADD函数计算,你可以发现很多不同的可能有意义的日期。  

      目前为止的所有例子只是仅仅计算当前的时间和“1900-01-01”之间的时间间隔数量,然后把它加到“1900-01-01”的时间间隔上来计算出日期。假定你修改时间间隔的数量,或者使用不同的时间间隔来调用DATEADD函数,或者减去时间间隔而不是增加,那么通过这些小的调整你可以发现和多不同的日期。  

      这里有四个例子使用另外一个DATEADD函数来计算最后一天来分别替换DATEADD函数前后两个时间间隔。  

上个月的最后一天  

      这是一个计算上个月最后一天的例子。它通过从一个月的最后一天这个例子上减去3毫秒来获得。有一点要记住,在Sql  Server中时间是精确到3毫秒。这就是为什么我需要减去3毫秒来获得我要的日期和时间。  

      SELECT  dateadd(ms,-3,DATEADD(mm,  DATEDIFF(mm,0,getdate()),  0))  

      计算出来的日期的时间部分包含了一个Sql  Server可以记录的一天的最后时刻(“23:59:59:997”)的时间。  

去年的最后一天  

      连接上面的例子,为了要得到去年的最后一天,你需要在今年的第一天上减去3毫秒。  

      SELECT  dateadd(ms,-3,DATEADD(yy,  DATEDIFF(yy,0,getdate()),  0))  

本月的最后一天  

      现在,为了获得本月的最后一天,我需要稍微修改一下获得上个月的最后一天的语句。修改需要给用DATEDIFF比较当前日期和“1900-01-01”返回的时间间隔上加1。通过加1个月,我计算出下个月的第一天,然后减去3毫秒,这样就计算出了这个月的最后一天。这是计算本月最后一天的SQL脚本。  

      SELECT  dateadd(ms,-3,DATEADD(mm,  DATEDIFF(m,0,getdate())+1,  0))  

本年的最后一天  

      你现在应该掌握这个的做法,这是计算本年最后一天脚本  

      SELECT  dateadd(ms,-3,DATEADD(yy,  DATEDIFF(yy,0,getdate())+1,  0))。  

本月的第一个星期一  

      好了,现在是最后一个例子。这里我要计算这个月的第一个星期一。这是计算的脚本。  

        select  DATEADD(wk,  DATEDIFF(wk,0,                                                          
                              dateadd(dd,6-datepart(day,getdate()),getdate())        
                                                                                                ),  0)                          

      在这个例子里,我使用了“本周的星期一”的脚本,并作了一点点修改。修改的部分是把原来脚本中“getdate()”部分替换成计算本月的第6天,在计算中用本月的第6天来替换当前日期使得计算可以获得这个月的第一个星期一。  

总结  

      我希望这些例子可以在你用DATEADD和DATEDIFF函数计算日期时给你一点启发。通过使用这个计算日期的时间间隔的数学方法,我发现为了显示两个日期之间间隔的有用历法是有价值的。注意,这只是计算出这些日期的一种方法。要牢记,还有很多方法可以得到相同的计算结果。假如你有其他的方法,那很不错,要是你没有,我希望这些例子可以给你一些启发,当你要用DATEADD和DATEDIFF函数计算你程序可能要用到的日期时。  

---------------------------------------------------------------  
附录,其他日期处理方法  

1)去掉时分秒  
declare  @  datetime  
set  @  =  getdate()  --'2003-7-1  10:00:00'  
SELECT  @,DATEADD(day,  DATEDIFF(day,0,@),  0)  

2)显示星期几  
select  datename(weekday,getdate())    

3)如何取得某个月的天数  
declare  @m  int  
set  @m=2  --月份  
select    datediff(day,'2003-'+cast(@m  as  varchar)+'-15'  ,'2003-'+cast(@m+1    as  varchar)+'-15')  
另外,取得本月天数  
select    datediff(day,cast(month(GetDate())  as  varchar)+'-'+cast(month(GetDate())  as  varchar)+'-15'  ,cast(month(GetDate())  as  varchar)+'-'+cast(month(GetDate())+1    as  varchar)+'-15')  
或者使用计算本月的最后一天的脚本,然后用DAY函数区最后一天  
SELECT  Day(dateadd(ms,-3,DATEADD(mm,  DATEDIFF(m,0,getdate())+1,  0)))  

4)判断是否闰年:  
SELECT  case  day(dateadd(mm,  2,  dateadd(ms,-3,DATEADD(yy,  DATEDIFF(yy,0,getdate()),  0))))  when  28  then  '平年'  else  '闰年'  end  
或者  
select  case  datediff(day,datename(year,getdate())+'-02-01',dateadd(mm,1,datename(year,getdate())+'-02-01'))  
when  28  then  '平年'  else  '闰年'  end  

5)一个季度多少天  
declare  @m  tinyint,@time  smalldatetime  
select  @m=month(getdate())  
select  @m=case  when  @m  between  1  and  3  then  1  
                      when  @m  between  4  and  6  then  4  
                      when  @m  between  7  and  9  then  7  
                      else  10  end  
select  @time=datename(year,getdate())+'-'+convert(varchar(10),@m)+'-01'  
select  datediff(day,@time,dateadd(mm,3,@time))
                         
/
KeyLife富翁笔记 
作者: goddy
标题: sql
关键字:
分类: 个人专区
密级: 公开
(评分: , 回复: 0, 阅读: 137) ??
1. 行列转换
假设有张学生成绩表(CJ)如下
Name    Subject     Result
张三    语文        80
张三    数学        90
张三    物理        85
李四    语文        85
李四    数学        92
李四    物理        82

想变成   
姓名   语文   数学   物理
张三   80     90     85
李四   85     92     82

解决如下
declare @sql varchar(4000)
set @sql = 'select Name'
select @sql = @sql + ',sum(case Subject when '''+Subject+''' then Result end) ['+Subject+']'
 from (select distinct Subject from CJ) as a
select @sql = @sql+' from test group by name'
exec(@sql)

另外在Access中还提供了TransForm来实现行列转换
TRANSFORM count(Result) AS number
SELECT 姓名
FROM 学生成绩表
GROUP BY 姓名
PIVOT Subject;

TransForm 用法如下:
=========================================================
TRANSFORM aggfunction
selectstatement
PIVOT pivotfield [IN (value1[, value2[, ...]])]

TRANSFORM 语句可分为以下几个部分:

部分            描述
aggfunction 在选定数据上运作的 SQL 合计函数。
selectstatement  SELECT 语句。
pivotfield 在查询的结果集中创建列标题时用的字段或表达式。
value1, value2 用来创建列标题的固定值。

说明
使用交叉表查询来摘要数据时,从指定的字段或表达式中选定值作为列标题,
这样,可以用比选定查询更紧凑的格式来观察数据。
TRANSFORM 是可选的,但在使用它时,要作为  SQL 字符串中的第一个语句。
它出现在 SELECT 语句(指定作为行标题的字段的)之前,还出现在 GROUP BY 子句
(指定行分组的)之前。可以有选择地包含其它子句,例如 WHERE 子句,它指定附
加的选择或排序条件。也可以将子查询当作谓词,特别是在叉表查询的 WHERE 子句中。

pivotfield 返回的值被用作查询结果集中的列标题。
例如,在交叉表查询中,将根据销售图表按销售月份创建 12 个列。
可以限制 pivotfield 用列在可选的 IN 子句中的固定值(value1, value2)来创建标题。
也可以用没有数据存在的固定值来创建附加的列。
==================================================================================

2. 列行转换
暂时保留

3. 行列转换--加合并
有表A,
 id pid
 1   1
 1   2
 1   3
 2   1
 2   2
 3   1
如何化成表B:
 id pid
  1  1,2,3
  2  1,2
  3  1

创建一个合并的函数
create function fmerg(@id int)
returns varchar(8000)
as
begin
declare @str varchar(8000)
set @str=''
select @str=@str+','+cast(pid as varchar) from 表A where id=@id
set @str=right(@str,len(@str)-1)
return(@str)
End
go

--调用自定义函数得到结果
select distinct id,dbo.fmerg(id) from 表A

4. 如何取得一个数据表的所有列名
方法如下:先从SYSTEMOBJECT系统表中取得数据表的SYSTEMID,然后再SYSCOLUMN表中取得该数据表的所有列名。
SQL语句如下:
declare @objid int,@objname char(40)
set @objname = 'tablename'
select @objid = id from sysobjects where id = object_id(@objname)
select 'Column_name' = name from syscolumns where id = @objid order by colid

是不是太简单了? 呵呵 不过经常用阿.

5. 通过SQL语句来更改用户的密码

修改别人的,需要sysadmin  role   
EXEC  sp_password  NULL,  'newpassword',  'User'

如果帐号为SA执行EXEC  sp_password  NULL,  'newpassword',  sa 

6.怎么判断出一个表的哪些字段不允许为空?

select  COLUMN_NAME  from  INFORMATION_SCHEMA.COLUMNS  where  IS_NULLABLE='NO'  and  TABLE_NAME=tablename 

7.如何在数据库里找到含有相同字段的表?
a. 查已知列名的情况
SELECT  b.name  as  TableName,a.name  as  columnname 
From  syscolumns    a  INNER  JOIN    sysobjects  b   
ON  a.id=b.id   
AND  b.type='U'   
AND  a.name='你的字段名字' 
b. 未知列名查所有在不同表出现过的列名
Select  o.name  As  tablename,s1.name  As  columnname 
From  syscolumns  s1,  sysobjects  o 
Where  s1.id  =  o.id 
   And  o.type  =  'U' 
   And  Exists  ( 
       Select  1  From  syscolumns  s2   
       Where  s1.name  =  s2.name   
       And  s1.id  <>  s2.id 
       )
8.查询第xxx行数据

假设id是主键: 
select  * 
from  (select  top  xxx  *  from  yourtable)  aa 
where  not  exists(select  1  from  (select  top  xxx-1  *  from  yourtable)  bb  where  aa.id=bb.id)
如果使用游标也是可以的 
fetch  absolute  [number]  from  [cursor_name] 
行数为绝对行数

9.SQL Server日期计算
a. 一个月的第一天
SELECT  DATEADD(mm,  DATEDIFF(mm,0,getdate()),  0) 
b. 本周的星期一
SELECT  DATEADD(wk,  DATEDIFF(wk,0,getdate()),  0)
c. 一年的第一天
SELECT  DATEADD(yy,  DATEDIFF(yy,0,getdate()),  0) 
d. 季度的第一天
SELECT  DATEADD(qq,  DATEDIFF(qq,0,getdate()),  0) 
e. 上个月的最后一天
SELECT  dateadd(ms,-3,DATEADD(mm,  DATEDIFF(mm,0,getdate()),  0)) 
f. 去年的最后一天
SELECT  dateadd(ms,-3,DATEADD(yy,  DATEDIFF(yy,0,getdate()),  0))
g. 本月的最后一天
SELECT  dateadd(ms,-3,DATEADD(mm,  DATEDIFF(m,0,getdate())+1,  0)) 
h. 本月的第一个星期一
select  DATEADD(wk,  DATEDIFF(wk,0,                                                         
                               dateadd(dd,6-datepart(day,getdate()),getdate())       
                                                                                                 ),  0)     
i. 本年的最后一天
SELECT  dateadd(ms,-3,DATEADD(yy,  DATEDIFF(yy,0,getdate())+1,  0))。

//
保存 评价 游戏规则 免费注册  资料下载 关于本站 
问题分类 编程问题 非技术题 富翁列表 我的信息 提出问题 在线富翁 富翁日历 笔记列表 我的笔记 写作笔记 全文检索 《专家门诊》 

富翁名称: guolei0451
专 家 分: 0
可用积分: 94

退出论坛
 

--------------------------------------------------------------------------------

友站直通车 !


管理我的信息
富翁之家模板
聊天室记事本
我的待答问题
我的已答问题
我收藏的问题
我参与的问题
查关键词 
检索LID 

--------------------------------------------------------------------------------


--------------------------------------------------------------------------------

大富翁论坛版权所有
 KeyLife富翁笔记 
作者: HrSoft
标题: SQL语句特殊技巧吧
关键字:
分类: 个人专区
密级: 公开
(评分: , 回复: 0, 阅读: 450) ??
上次写了个ACCESS技巧集,反映良好,这次来个SQL语句特殊技巧吧

1.把某个字段重新生气序列(从1到n):
DECLARE @i int
Set @i = 0
Update Table1 Set @i = @i + 1,Field1 = @i

2.按成绩排名次
Update 成绩表
Set a.名次 = (
  Select Count(*) + 1
  From 成绩表 b
  Where a.总成绩 < b.总成绩
)
From 成绩表 a

3.查询外部数据库
Select a.*
From OpenRowSet('Microsoft.Jet.OLEDB.4.0','c:/test.mdb';'admin';'',Table1) a

4.查询Excel文件
Select *
From OpenDataSource('Microsoft.Jet.OLEDB.4.0','Data Source="c:/test.xls";User ID=Admin;Password=;Extended properties=Excel 8.0')...Sheet1$

5.在查询中指定排序规则
Select * From Table1 Order By Field1 COLLATE Chinese_PRC_BIN
为什么要指定排序规则呢?参见:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1633985
例,检查数据库中的Pub_Users表中是否存在指定的用户:
Select Count(*) From Pub_Users Where [UserName]='admin' And [PassWord]='aaa' COLLATE Chinese_PRC_BIN
默认比较是不区分大小写的,如果不加COLLATE Chinese_PRC_BIN,那么密码aaa与AAA是等效的,这当然与实际不符.注意的是,每个条件都要指定排序规则,上例中用户名就不区分大小写.


6.Order By的一个小技巧
Order By可以指定列序而不用指定列名,在下面的例子里说明它的用处(注意,第三列未指定别名)
Select a.ID,a.Name,(Select Count(*) From TableB b Where a.ID=b.PID) From TableA a Order By 3

待续...

2003-10-6 13:53:00   
 发表评语»»»    

 2003-12-6 19:36:00    7.字符串之Sum???例如,有个表
  ID   NAME
------------------
  1     T
  2     H
  3     A
  4     N
  5     K
要得到
THANK

declare @s varchar(100);
set @s='';
select @s=@s+[Name] from 表 order by id;
select @s;
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2290831

 
 2005-10-10 12:56:05    再来一个排名的,没有排名字段查询排名create table t1
(khid varchar(10), xsje money)

insert into t1 values ('001',100)
insert into t1 values ('002',105)
insert into t1 values ('003',220)
insert into t1 values ('004',89)
insert into t1 values ('001',150)
insert into t1 values ('002',50)
insert into t1 values ('003',38)

select (
    select count(*) + 1 from (
        select khid,sum(xsje) as xsje from t1 group by khid
    ) b where a.xsje < b.xsje
) mc,* from (
    select khid,sum(xsje) as xsje from t1 group by khid
) a order by mc

优点:允许并列排名,纯查询
缺点:要做两次sum扫描源表
问题见:http://www.delphibbs.com/delphibbs/dispq.asp?lid=3231593

修改一下以适应于ACCESS
select (
    select count(*) + 1 from (
        select khid,sum(xsje) as xsje_sum from t1 group by khid
    ) as b where a.xsje_sum < b.xsje_sum
) as mc,* from (
    select khid,sum(xsje) as xsje_sum from t1 group by khid
) as a order by xsje_sum desc  
/
保存 评价 游戏规则 免费注册  资料下载 关于本站 
问题分类 编程问题 非技术题 富翁列表 我的信息 提出问题 在线富翁 富翁日历 笔记列表 我的笔记 写作笔记 全文检索 《专家门诊》 

富翁名称: guolei0451
专 家 分: 0
可用积分: 94

退出论坛
 

--------------------------------------------------------------------------------

友站直通车 !


管理我的信息
富翁之家模板
聊天室记事本
我的待答问题
我的已答问题
我收藏的问题
我参与的问题
查关键词 
检索LID 

--------------------------------------------------------------------------------


--------------------------------------------------------------------------------

大富翁论坛版权所有
 KeyLife富翁笔记 
作者: cg.410
标题: SQL基础知识大全
关键字:
分类: 个人专区
密级: 公开
(评分: , 回复: 0, 阅读: 2376) ??
SQL基础知识大全
   SQL语言由命令、子句、运算和集合函数等构成。在SQL中,数据定义语言DDL(用来建立及定义数据表、字段以及索引等数据库结构)包含的命令有CREATE、DROP、ALTER;数据操纵语言DML(用来提供数据的查询、排序以及筛选数据等功能)包含的命令有SELECT、INSERT、UPDATE、DELETE。

一、SQL语句

(1)Select 查询语句
语法:SELECT [ALL|DISTINCT] <目标列表达式> [AS 列名]
[,<目标列表达式> [AS 列名] ...] FROM <表名> [,<表名>…]
[WHERE <条件表达式> [AND|OR <条件表达式>...]
[GROUP BY 列名 [HAVING <条件表达式>]]
[ORDER BY 列名 [ASC | DESC]]
解释:[ALL|DISTINCT]   ALL:全部; DISTINCT:不包括重复行
<目标列表达式> 对字段可使用AVG、COUNT、SUM、MIN、MAX、运算符等
<条件表达式>
查询条件 谓词
比较 =、>,<,>=,<=,!=,<>,
确定范围 BETWEEN AND、NOT BETWEEN AND
确定集合 IN、NOT IN
字符匹配 LIKE(“%”匹配任何长度,“_”匹配一个字符)、NOT LIKE
空值 IS NULL、IS NOT NULL
子查询 ANY、ALL、EXISTS
集合查询 UNION(并)、INTERSECT(交)、MINUS(差)
多重条件 AND、OR、NOT
对查询结果分组
[HAVING <条件表达式>] 分组筛选条件
[ORDER BY 列名 [ASC | DESC]] 对查询结果排序;ASC:升序 DESC:降序
例1: select student.sno as 学号, student.name as 姓名, course as 课程名, score as 成绩 from score,student where student.sid=score.sid and score.sid=:sid
例2:select student.sno as 学号, student.name as 姓名,AVG(score) as 平均分 from score,student where student.sid=score.sid and student.class=:class and (term=5 or term=6) group by student.sno, student.name having count(*)>0 order by 平均分 DESC
例3:select * from score where sid like '9634'
例4:select * from student where class in (select class from student where name='陈小小')

(2)INSERT插入语句
语法:INSERT INTO <表名> [(<字段名1> [,<字段名2>, ...])] VALUES (<常量1> [,<常量2>, ...])
语法:INSERT INTO <表名> [(<字段名1> [,<字段名2>, ...])] 子查询
例子:INSERT INTO 借书表(rid,bookidx,bdate)VALUES (edit1.text,edit2.text,date)
例子:INSERT INTO score1(sno,name) SELECT sno,name FROM student WHERE class=’9634’

(3)UPDATE-SQL
语法:UPDATE 〈表名〉
SET 列名1 = 常量表达式1[,列名2 = 常量表达式2 ...]
WHERE <条件表达式> [AND|OR <条件表达式>...]
例子:update score set credithour=4 where course='数据库'

(4)DELETE-SQL
语法:DELETE FROM〈表名〉[WHERE <条件表达式> [AND|OR <条件表达式>...]]
例子:Delete from student where sid='003101'

(5)CREATE TABLE
CREATE TABLE | DBF TableName1 [NAME LongTableName] [FREE]
(FieldName1 FieldType [(nFieldWidth [, nPrecision])]
  [NULL | NOT NULL]
  [CHECK lExpression1 [ERROR cMessageText1]]
  [DEFAULT eExpression1]
  [PRIMARY KEY | UNIQUE]
  [REFERENCES TableName2 [TAG TagName1]]
  [NOCPTRANS]
[, FieldName2 ...]
  [, PRIMARY KEY eExpression2 TAG TagName2
|, UNIQUE eExpression3 TAG TagName3]
  [, FOREIGN KEY eExpression4 TAG TagName4 [NODUP]
  REFERENCES TableName3 [TAG TagName5]]
  [, CHECK lExpression2 [ERROR cMessageText2]])
| FROM ARRAY ArrayName

(6)ALTER TABLE
ALTER TABLE TableName1
ADD | ALTER [COLUMN] FieldName1
  FieldType [(nFieldWidth [, nPrecision])]
  [NULL | NOT NULL]
  [CHECK lExpression1 [ERROR cMessageText1]]
  [DEFAULT eExpression1]
  [PRIMARY KEY | UNIQUE]
  [REFERENCES TableName2 [TAG TagName1]]
  [NOCPTRANS]

(7)DROP TABLE
DROP TABLE [路径名.]表名

(8)CREATE INDEX
CREATE INDEX index-name ON table-name(column[,column…])
例:CREATE INDEX uspa ON 口令表(user,password)

(9)DROP INDEX
DROP INDEX table-name.index-name|PRIMARY
例:DROP INDEX 口令表.uspa

二、在程序中使用静态SQL语句
  在程序设计阶段,将SQL命令文本作为TQuery组件的SQL属性值设置。

三、在程序中使用动态SQL语句
  动态SQL语句是指在SQL语句中包含有参数变量的SQL语句(如:select * from student where class=:class),在程序中可以为参数赋值。给参数赋值的方法有:

  1、利用参数编辑器为参数赋值
  选中TQuery组件,在对象监视器OI中点取Params项,在弹出的参数编辑窗口中设置参数的值。
例:SELECT bookidx AS 书号,藏书表.bookname AS 书名, bdate AS 借书日期 FROM 借书表,藏书表 where 借书表.bookidx=藏书表.bookidx and rid=:rid

  2、在程序运行中通过程序为参数赋值
(1)根据参数在SQL语句中出现的顺序,使用TQuery的Params属性为参数赋值;

例:在借书表中插入一条记录
with Query1 do
begin
  SQL.clear;
  SQL.add('Insert Into 借书表(bookidx,rid,rdate)');
  SQl.add('Values(:bookidx,:rid,:rdate)');
  Params[0].AsString := bookidxEdit.Text;
  Params[1].AsString := ridEdit.Text;
  Params[2] .AsDate:=date;
  ExecSQL;
End;

(2)根据SQL语句中的参数名字,调用ParamByName方法为参数赋值;
ParamByName('bookidx').AsString := bookidxEdit.Text;
ParamByName('rid').AsString := ridEdit.Text;
ParamByName('rdate') .AsDate:=date;
ExecSQL;
有:AsString 、AsSmallInt 、AsInteger 、AsWord 、AsBoolean 、AsFloat 、AsCurrency 、AsBCD 、AsDate 、AsTime 、AsDateTime转换函数

3、使用数据源为参数赋值
  把TQuery的DataSource属性设置为另一个数据源(T DataSource名字),Delphi会把未赋值的参数与指定的数据源中的各字段相比较,并将匹配的字段的值赋给未赋值的参数,可实现主表—明细表应用。

四、对TQuery返回的数据集进行修改
  一般情况下,TQuery返回的数据集是只读的,不能修改;
  对不包含集操作(如:SUM、COUNT)的单表SELECT查询,设置TQuery的RequsetLive属性为True,则可修改TQuery返回的数据集。

var
I: Integer;
ListItem: string;
begin
for I := 0 to Query1.ParamCount - 1 do
begin
  ListItem := ListBox1.Items[I];
  case Query1.Params[I].DataType of
    ftString:
    Query1.Params[I].AsString := ListItem;
    ftSmallInt:
    Query1.Params[I].AsSmallInt := StrToIntDef(ListItem, 0);
    ftInteger:
    Query1.Params[I].AsInteger := StrToIntDef(ListItem, 0);
    ftWord:
    Query1.Params[I].AsWord := StrToIntDef(ListItem, 0);
    ftBoolean:
    begin
      if ListItem = 'True' then
        Query1.Params[I].AsBoolean := True
      else
        Query1.Params[I].AsBoolean := False;
    end;
    ftFloat:
    Query1.Params[I].AsFloat := StrToFloat(ListItem);
    ftCurrency:
    Query1.Params[I].AsCurrency := StrToFloat(ListItem);
    ftBCD:
    Query1.Params[I].AsBCD := StrToCurr(ListItem);
    ftDate:
    Query1.Params[I].AsDate := StrToDate(ListItem);
    ftTime:
    Query1.Params[I].AsTime := StrToTime(ListItem);
    ftDateTime:
    Query1.Params[I].AsDateTime := StrToDateTime(ListItem);
  end;
end;
end;


2003-11-25 9:59:00  
查看评语???  

2003-11-25 10:06:20   运行期间对数据库表的
一、数据集表的打开与关闭
打开:设置数据集组件的Active属性为True或调用数据集组件的Open方法
关闭:设置数据集组件的Active属性为False或调用数据集组件的Close方法

二、创建数据库应用程序
?利用向导创建:使用Database菜单/Form Wizard选项;
?创建主从表:设置从表的MasterSource、MasterField属性;
?创建查询表:使用TQuery组件;

三、数据库表记录的定位
?使用TDBNavigator组件;
?调用数据集组件的First、Next、Prior、Last方法;
?数据集组件的EOF属性(或BOF属性)用来判断记录指针是否指向第一条记录(或最后一条记录);
?使用数据集的书签BookMark(GetBookMark:获得当前记录的BookMark记号;GotoBookMark:从当前记录直接转到指定BookMark的那条记录;FreeBookMark:释放某个BookMark)
?使用GotoKey、FindKey方法查找记录进行定位;

四、数据库表字段对象的使用

(1)创建永久的字段对象
  双击或单击再右击TTable(TQuery)对象打开字段编辑器,使用其弹出菜单增加字段对象、删除字段对象、定义新的字段对象(字段编辑器的弹出菜单的New Fields选项,可创建计算字段);

(2)字段对象的属性、方法、事件
  字段对象名:如Table1Name、Query1Sid
  属性:Alignment(对齐方式)、Calculated(是否是从其它字段值计算得到)、DisplayLabel(显示的标题)、DisplayWidth(显示的宽度)、DisplayFormat(显示的格式)、EditMask(输入的限制)、FieldName(字段名)、ReadOnly(是否只读)、Visible(是否显示)
  事件:OnChange(字段值发生变化时触发)、OnGetText(当字段对象获得字段值时触发)、OnSetText(当字段对象被设置字段值时触发)、OnValiData(当修改、插入、进行有效性检验时触发)

(3)字段对象的类型转换
  有:AsString 、AsSmallInt 、AsInteger 、AsWord 、AsBoolean 、AsFloat 、AsCurrency 、AsBCD 、AsDate 、AsTime 、AsDateTime转换函数
如:Edit1.Text:=Table1Name.Value ;
Table1Bdate.AsString:=DateToStr(DATE) ;

(4)对字段对象的访问
  动态字段对象的访问:Table1.Fields[0]. DisplayLabel:= '学生编号'
Table1.FieldByName('Sid'). DisplayLabel:= '学生编号' Table1.Fields[0].Assignment:=taCenter
Edit1.Text:= Table1.FieldByName('Sid').AsString
  永久字段对象的访问:Query1Sid.DisplayLabel:= '学生编号'
Query1Sid.DisplayWidth:= 12

五、对数据库表数据的操作方法

(1)访问表中某一字段的数据的方法:
?Table1.FieldByName('bookidx').AsString
?Table1.Field[0].AsInteger
?Table1.Fieldvalues['bookidx']

(2)数据库表的一些属性:
?当前记录号:Table1.Recno
?记录总数:Table1.RecordCount
?得到表的字段名:Table1.GetFieldNames(ListBox1。Items)

(3)数据维护的方法:
?Edit方法:把数据集设置为编辑状态;
?Append方法:把数据集设置为插入状态(最后);
?Insert方法:把数据集设置为插入状态(当前记录后);
?Post方法:把修改的记录写回数据集;
?Cancel方法:取消当前的操作;
?Delete方法:删除表中当前记录;
?AppendRecord方法:
?InsertRecord方法:table1.InsertRecord(['963409', NIL, NIL,'考试']);
?SetRecords方法:
?Abort方法:取消各种方法的调用;

(4)输入数据的合法性验证
  对数据库表建立合法性验证机制(如在DBD设置表的Validity Check、Table Lookup、Referential Integrity等属性);
? 在字段编辑表Fields Editor(双击Ttable对象),选择字段,编写其OnValidate事件,要求非空可设置其Required属性为True;
? 在程序中防止不合法输入(如:使用TDBcombobox对象,TDBlookupcombobox对象);

六、数据检索
(1)利用索引排序
  如:TABLE1.IndexName:='uspa' 或TABLE1.IndexFieldNames:='user_id'
(2)使用GotoKey方法查找数据库中的记录
? 要求查找字段建立了索引,非主索引要设置Ttable对象的IndexName属性。
? 调用SetKey方法,把要查找的Ttable对象置成查找模块;
? 把查找值送进被查找的Field的查找缓冲区;
? 调用Ttable对象的GotoKey方法,测试该方法的返回值判断查找是否成功;
(3)使用FindKey方法查找数据库中的记录
  把查找值作为参数传递给FindKey函数,允许有多个查找值,要求把要查找的多个字段的索引名赋给Ttable对象的IndexName属性;
(4)不精确查找
  GotoNearest方法
  FindNearest方法
(5)使用Locate方法查找数据库中的记录(不用建索引)
  table1.locate(‘字段名1;字段名2’,VarArroyof([‘值1’,‘值2’]),[LoCaseInsensitive,LoPartialKey])
  LoCaseInsensitive:忽略大小写;IoPartialKey:不精确查找
(6)设定查找范围的方法
  SetRangeStart、SetRangeEnd、EditRangeStart、EditRangeEnd、SetRange([Start Values],[End Value])、ApplyRange、CancelRange
(7)用TQuery组件的动态SQL语句进行查找

七、修改数据库中的记录
  在程序中对数据库记录进行操作可按下列的步骤进行:
(1)移动数据指针到要修改的记录;
(2)调用Edit方法将Ttable组件设置成编辑状态;
(3)修改字段值;(Table1.Fieldvalues['字段名']:=值、Table1.Field[0].AsString:=值)
(4)可用Nil对字段赋空值;
(5)调用Post方法将修改后的记录写入数据库;

八、插入和删除记录
  删除:移动指针到相应记录处,调用Delete方法;
  插入:调用Insert、InsertRecord方法(当前记录处插入)或Append、InsertRecord方法(表的末尾插入);


2003-11-25 10:11:12   动态的添加PARADOX表的方法【王寒松】下面给出的函数 AddMasterPassword 完成添加PARADOX表主口令的工作
AddMasterPassword(Table1, 'MyNewPassword')
procedure AddMasterPassword(Table: TTable; pswd: string);
const
  RESTRUCTURE_TRUE = WordBool(1);
var
  TblDesc: CRTblDesc;
  hDb: hDBIDb;
begin
  {表打开?表是独占吗?}
  if (Table.Active = False) or (Table.Exclusive = False) then
    raise EDatabaseError.Create('数据表必须在独占方式才可以添加口令');
  {初始化表描述区 }
  FillChar(TblDesc, SizeOf(CRTblDesc), 0);
  with TblDesc do
  begin
    { 把表名放到描述区 }
    StrPCopy(szTblName, Table.TableName);
    { 把表类型放到描述区 }
    StrCopy(szTblType, szPARADOX);
    StrPCopy(szPassword, pswd);
    { 设置BPROTECTED为TRUE }
    bProtected := RESTRUCTURE_TRUE;
  end;
  { 从当前的HANDLE里得到DATABASE的HANDLE }
  Check(DbiGetObjFromObj(hDBIObj(Table.Handle), objDATABASE, hDBIObj(hDb)));
  { 关闭表 }
  Table.Close;
  { 添加主口令到PARADOX表里}
  Check(DbiDoRestructure(hDb, 1, @TblDesc, nil, nil, nil, FALSE));
  {添加一个新口令到SESSION}
  Session.AddPassword(pswd);
  {重新打开表 }
  Table.Open;
end;
添加副口令的办法与此类似


2003-11-25 11:21:29   如何选择一个好的数据库【三大数据库比较】
【开放性】

SQL Server
  只能在windows 上运行,没有丝毫的开放性,操作系统的系统的稳定对数据库是十分重要的。Windows9X系列产品是偏重于桌面应用,NT server只适合中小型企业。而且windows平台的可靠性,安全性和伸缩性是非常有限的。它不象unix那样久经考验,尤其是在处理大数据量的关键业务时.

Oracle
  能在所有主流平台上运行(包括 windows)。完全支持所有的工业标准。采用完全开放策略。可以使客户选择最适合的解决方案。对开发商全力支持。

DB2
  能在所有主流平台上运行(包括windows)。最适于海量数据。DB2在企业级的应用最为广泛,在全球的500家最大的企业中,几乎85%以上用DB2数据库服务器,而国内到97年约占5%.


【可伸缩性,并行性】

SQL server
  并行实施和共存模型并不成熟。很难处理日益增多的用户数和数据卷。伸缩性有限。

Oracle
  平行服务器通过使一组结点共享同一簇中的工作来扩展windownt的能力,提供高可用性和高伸缩性的簇的解决方案。如果windowsNT不能满足需要, 用户可以把数据库移到UNIX中。

DB2  
  DB2具有很好的并行性。DB2把数据库管理扩充到了并行的、多节点的环境.数据库分区是数据库的一部分,包含自己的数据、索引、配置文件、和事务日志。数据库分区有时被称为节点或数据库节点


【安全性】

SQL server
  没有获得任何安全证书。

Oracle Server
  获得最高认证级别的ISO标准认证。

DB2
  获得最高认证级别的ISO标准认证。


【性能】

SQL Server
  多用户时性能不佳

Oracle
  性能最高, 保持windowsNT下的TPC-D和TPC-C的世界记录。

DB2
  适用于数据仓库和在线事物处理,性能较高。


【客户端支持及应用模式】

SQL Server
  C/S结构,只支持windows客户,可以用ADO,DAO,OLEDB,ODBC连接.

Oracle
  多层次网络计算,支持多种工业标准,可以用ODBC,JDBC,OCI等网络客户连接

DB2
  跨平台,多层结构,支持ODBC,JDBC等客户


【操作简便】

SQL Server
  操作简单,但只有图形界面.

Oracle
  较复杂, 同时提供GUI和命令行,在windowsNT和unix下操作相同

DB2
  操作简单,同时提供GUI和命令行,在windowsNT和unix下操作相同


【使用风险】

SQL server
  完全重写的代码,经历了长期的测试,不断延迟,许多功能需要时间来证明。并不十分兼容早期产品。使用需要冒一定风险。

Oracle
  长时间的开发经验,完全向下兼容。得到广泛的应用。完全没有风险。

DB2
  在巨型企业得到广泛的应用,向下兼容性好。风险小。


2003-11-25 11:25:37   SQL查询语句使用一、简单查询
  简单的Transact-SQL查询只包括选择列表、FROM子句和WHERE子句。它们分别说明所查询列、查询的表或视图、以及搜索条件等。
  例如,下面的语句查询testtable表中姓名为“张三”的nickname字段和email字段。
  SELECT nickname,email
  FROM testtable
  WHERE name='张三'

(一)选择列表
  选择列表(select_list)指出所查询列,它可以是一组列名列表、星号、表达式、变量(包括局部变量和全局变量)等构成。

  1、选择所有列
  例如,下面语句显示testtable表中所有列的数据:
  SELECT *
  FROM testtable

  2、选择部分列并指定它们的显示次序
  查询结果集合中数据的排列顺序与选择列表中所指定的列名排列顺序相同。
  例如:
  SELECT nickname,email
  FROM testtable

  3、更改列标题
  在选择列表中,可重新指定列标题。定义格式为:
  列标题=列名
  列名 列标题
  如果指定的列标题不是标准的标识符格式时,应使用引号定界符,例如,下列语句使用汉字显示列标题:
  SELECT 昵称=nickname,电子邮件=email
  FROM testtable

  4、删除重复行
  SELECT语句中使用ALL或DISTINCT选项来显示表中符合条件的所有行或删除其中重复的数据行,默认为ALL。使用DISTINCT选项时,对于所有重复的数据行在SELECT返回的结果集合中只保留一行。

  5、限制返回的行数
  使用TOP n [PERCENT]选项限制返回的数据行数,TOP n说明返回n行,而TOP n PERCENT时,说明n是表示一百分数,指定返回的行数等于总行数的百分之几。
  例如:
  SELECT TOP 2 *
  FROM testtable
  SELECT TOP 20 PERCENT *
  FROM testtable

(二)FROM子句
  FROM子句指定SELECT语句查询及与查询相关的表或视图。在FROM子句中最多可指定256个表或视图,它们之间用逗号分隔。
  在FROM子句同时指定多个表或视图时,如果选择列表中存在同名列,这时应使用对象名限定这些列所属的表或视图。例如在usertable和citytable表中同时存在cityid列,在查询两个表中的cityid时应使用下面语句格式加以限定:

  SELECT username,citytable.cityid
    FROM usertable,citytable
    WHERE usertable.cityid=citytable.cityid
  在FROM子句中可用以下两种格式为表或视图指定别名:
  表名 as 别名
  表名 别名

  例如上面语句可用表的别名格式表示为:
  SELECT username,b.cityid
    FROM usertable a,citytable b
    WHERE a.cityid=b.cityid
 
  SELECT不仅能从表或视图中检索数据,它还能够从其它查询语句所返回的结果集合中查询数据。
  例如:
  SELECT a.au_fname+a.au_lname
    FROM authors a,titleauthor ta
    (SELECT title_id,title
      FROM titles
      WHERE ytd_sales>10000
    ) AS t
    WHERE a.au_id=ta.au_id
    AND ta.title_id=t.title_id
  此例中,将SELECT返回的结果集合给予一别名t,然后再从中检索数据。

(三)使用WHERE子句设置查询条件
  WHERE子句设置查询条件,过滤掉不需要的数据行。例如下面语句查询年龄大于20的数据:
  SELECT *
    FROM usertable
    WHERE age>20

  WHERE子句可包括各种条件运算符:
  比较运算符(大小比较):>、>=、=、<、<=、<>、!>、!<
  范围运算符(表达式值是否在指定的范围):BETWEEN…AND…
                            NOT BETWEEN…AND…
  列表运算符(判断表达式是否为列表中的指定项):IN (项1,项2……)
                                NOT IN (项1,项2……)
  模式匹配符(判断值是否与指定的字符通配格式相符):LIKE、NOT LIKE
  空值判断符(判断表达式是否为空):IS NULL、NOT IS NULL
  逻辑运算符(用于多条件的逻辑连接):NOT、AND、OR

  1、范围运算符例:age BETWEEN 10 AND 30相当于age>=10 AND age<=30
  2、列表运算符例:country IN ('Germany','China')
  3、模式匹配符例:常用于模糊查找,它判断列值是否与指定的字符串格式相匹配。可用于char、varchar、text、ntext、datetime和smalldatetime等类型查询。
  可使用以下通配字符:
  百分号%:可匹配任意类型和长度的字符,如果是中文,请使用两个百分号即%%。
  下划线_:匹配单个任意字符,它常用来限制表达式的字符长度。
  方括号[]:指定一个字符、字符串或范围,要求所匹配对象为它们中的任一个。
  [^]:其取值也[] 相同,但它要求所匹配对象为指定字符以外的任一个字符。

  例如:
  限制以Publishing结尾,使用LIKE '%Publishing'
  限制以A开头:LIKE '[A]%'
  限制以A开头外:LIKE '[^A]%'
 
  4、空值判断符例WHERE age IS NULL

  5、逻辑运算符:优先级为NOT、AND、OR

(四)查询结果排序
  使用ORDER BY子句对查询返回的结果按一列或多列排序。ORDER BY子句的语法格式为:
  ORDER BY {column_name [ASC|DESC]} [,…n]
  其中ASC表示升序,为默认值,DESC为降序。ORDER BY不能按ntext、text和image数据类型进行排序。
  例如:
  SELECT *
    FROM usertable
    ORDER BY age desc,userid ASC
  另外,可以根据表达式进行排序。

二、联合查询
  UNION运算符可以将两个或两个以上上SELECT语句的查询结果集合合并成一个结果集合显示,即执行联合查询。UNION的语法格式为:
  select_statement
    UNION [ALL] selectstatement
    [UNION [ALL] selectstatement][…n]
  其中selectstatement为待联合的SELECT查询语句。
  ALL选项表示将所有行合并到结果集合中。不指定该项时,被联合查询结果集合中的重复行将只保留一行。
  联合查询时,查询结果的列标题为第一个查询语句的列标题。因此,要定义列标题必须在第一个查询语句中定义。要对联合查询结果排序时,也必须使用第一查询语句中的列名、列标题或者列序号。
  在使用UNION 运算符时,应保证每个联合查询语句的选择列表中有相同数量的表达式,并且每个查询选择表达式应具有相同的数据类型,或是可以自动将它们转换为相同的数据类型。在自动转换时,对于数值类型,系统将低精度的数据类型转换为高精度的数据类型。
  在包括多个查询的UNION语句中,其执行顺序是自左至右,使用括号可以改变这一执行顺序。例如:
  查询1 UNION (查询2 UNION 查询3)

三、连接查询
  通过连接运算符可以实现多个表查询。连接是关系数据库模型的主要特点,也是它区别于其它类型数据库管理系统的一个标志。
  在关系数据库管理系统中,表建立时各数据之间的关系不必确定,常把一个实体的所有信息存放在一个表中。当检索数据时,通过连接操作查询出存放在多个表中的不同实体的信息。连接操作给用户带来很大的灵活性,他们可以在任何时候增加新的数据类型。为不同实体创建新的表,尔后通过连接进行查询。
  连接可以在SELECT 语句的FROM子句或WHERE子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与WHERE子句中的搜索条件区分开来。所以,在Transact-SQL中推荐使用这种方法。
  SQL-92标准所定义的FROM子句的连接语法格式为:
  FROM join_table join_type join_table
    [ON (join_condition)]
  其中join_table指出参与连接操作的表名,连接可以对同一个表操作,也可以对多表操作,对同一个表操作的连接又称做自连接。
  join_type 指出连接类型,可分为三种:内连接、外连接和交叉连接。内连接(INNER JOIN)使用比较运算符进行表间某(些)列数据的比较操作,并列出这些表中与连接条件相匹配的数据行。根据所使用的比较方式不同,内连接又分为等值连接、自然连接和不等连接三种。
  外连接分为左外连接(LEFT OUTER JOIN或LEFT JOIN)、右外连接(RIGHT OUTER JOIN或RIGHT JOIN)和全外连接(FULL OUTER JOIN或FULL JOIN)三种。与内连接不同的是,外连接不只列出与连接条件相匹配的行,而是列出左表(左外连接时)、右表(右外连接时)或两个表(全外连接时)中所有符合搜索条件的数据行。
  交叉连接(CROSS JOIN)没有WHERE 子句,它返回连接表中所有数据行的笛卡尔积,其结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。
  连接操作中的ON (join_condition) 子句指出连接条件,它由被连接表中的列和比较运算符、逻辑运算符等构成。
  无论哪种连接都不能对text、ntext和image数据类型列进行直接连接,但可以对这三种列进行间接连接。例如:
  SELECT p1.pub_id,p2.pub_id,p1.pr_info
    FROM pub_info AS p1 INNER JOIN pub_info AS p2
    ON DATALENGTH(p1.pr_info)=DATALENGTH(p2.pr_info)

  (一)内连接
  内连接查询操作列出与连接条件匹配的数据行,它使用比较运算符比较被连接列的列值。内连接分三种:
  1、等值连接:在连接条件中使用等于号(=)运算符比较被连接列的列值,其查询结果中列出被连接表中的所有列,包括其中的重复列。
  2、不等连接: 在连接条件使用除等于运算符以外的其它比较运算符比较被连接的列的列值。这些运算符包括>、>=、<=、<、!>、!<和<>。
  3、自然连接:在连接条件中使用等于(=)运算符比较被连接列的列值,但它使用选择列表指出查询结果集合中所包括的列,并删除连接表中的重复列。
  例,下面使用等值连接列出authors和publishers表中位于同一城市的作者和出版社:
  SELECT *
    FROM authors AS a INNER JOIN publishers AS p
    ON a.city=p.city

  又如使用自然连接,在选择列表中删除authors 和publishers 表中重复列(city和state):
  SELECT a.*,p.pub_id,p.pub_name,p.country
    FROM authors AS a INNER JOIN publishers AS p
    ON a.city=p.city

  (二)外连接
  内连接时,返回查询结果集合中的仅是符合查询条件( WHERE 搜索条件或 HAVING 条件)和连接条件的行。而采用外连接时,它返回到查询结果集合中的不仅包含符合连接条件的行,而且还包括左表(左外连接时)、右表(右外连接时)或两个边接表(全外连接)中的所有数据行。
  如下面使用左外连接将论坛内容和作者信息连接起来:
  SELECT a.*,b.* FROM luntan LEFT JOIN usertable as b
    ON a.username=b.username

  下面使用全外连接将city表中的所有作者以及user表中的所有作者,以及他们所在的城市:
  SELECT a.*,b.*
    FROM city as a FULL OUTER JOIN user as b
    ON a.username=b.username

  (三)交叉连接
  交叉连接不带WHERE 子句,它返回被连接的两个表所有数据行的笛卡尔积,返回到结果集合中的数据行数等于第一个表中符合查询条件的数据行数乘以第二个表中符合查询条件的数据行数。
  例,titles表中有6类图书,而publishers表中有8家出版社,则下列交叉连接检索到的记录数将等于6*8=48行。
  SELECT type,pub_name
    FROM titles CROSS JOIN publishers
    ORDER BY type


2003-11-25 11:31:30   SQL Server中Image Data Type的使用技巧 【国商网络有限公司 蒋心武】   MS SQL Server 是微软公司推出的大型数据库软件,在NT平台上拥有近一半的数据库市场,特别是在SQL Server 7.0推出后,其发展势头更加迅猛。SQL Server中Image数据类型是用来存储图形的。在此我谈谈怎样增、删、改此类型数据及在主页中读出此类型数据。

  一、在表中添加图形
  Image 数据类型不同于其它数据类型,不能用Insert 、Update的标准SQL语法进行图形的添加和修改。需用到SQL Server中的TEXTPTR 、WRITETEXT、UPDATETEXT等函数进行图形的添加和修改。

  首先假设在库Im_Test中建立一张表Im_Info,此表中有两个字段,分别为Pr_Id (INT),Pr_Info (IMAGE),用来存储图形编号及图形信息。其语法如下:

CREATE TEALE Im_Info (
  Pr_Id INT NULL ,
  Pr_Info IMAGE NULL
)

  第一步往表中插入一条记录,并初始化PR_INFO字段。其语法如下:

INSERT INTO Im_Info VALUES (1 ,0xFFFFFFFF)

  第二步往表中写入图形信息。其语法如下:

      DECLARE @@ptrval varbinary(16)
      SELECT @@ptrval = TEXTPTR(Pr_Info)
  FROM Im_Info
  WHERE Pr_Id = 1
      WRITETEXT Im_Text.Im_Info
        @@ptrval 0x624fd543fd…..

  其中0x624fd543fd….. 为图形的十六进制数据,可以通过C 、Java等工具获得。注意在写入图形信息前必须先将此数据库的 'select into/bulkcopy' 属性设置为 True ,其语法如下:

      sp_dboption Im_Test ,
      'select into/bulkcopy' ,True

  若想修改图形数据可用UPDATETEXT函数修改,其语法如下:

      DECLARE @@ptrval varbinary(16)
      SELECT @@ptrval = TEXTPTR(Pr_Info)
    FROM Im_Info
  WHERE Pr_Id = 1
      UPDATETEXT Im_Text.Im_Info
      @@ptrval 0xaa31bcfe543fd…..

  二、在主页中显示图形

  第一步建立数据源
  若想将加入的图形显示在主页中,必须先建立数据源,打开Windows 中的控制面板。通过ODBC 应用程序,建立数据源(取名Im_Test)连接到Im_Test数据库

  第二步编写程序
      < % @ LANGUAGE = VBScript % >
      < % Option Explicit % >
      < %
Dim oConn  
Dim oRs  
Dim Pic  
Dim PicSize  

Response.Buffer = TRUE
Response.ContentType = "image/gif"

Set oConn = Server.CreateObject ("ADODB.Connection")
oConn.Open "Im_Test",”sa”,””
Set oRs = oConn.Execute("SELECT Pr_Info FROM Im_Info WHERE Pr_Id=1”)

PicSize = oRs("Pr_Info").ActualSize
Pic = oRs("Pr_Info ").GetChunk(PicSize)

Response.BinaryWrite Pic
Response.End
      % >

  此程序中先定义四个变量。然后设置属性 Response.Buffer=TRU和Response.ContentType = "image/gif" ,再连接数据库取出图形,在加以显示。


2003-11-25 11:41:44   深入SQL编程【关于存储过程和索引】  这里所指的SQL编程并不是那些在象ASP,PHP脚本语言里用的某个SQL语句,如果你是个程序员并在做DB C/S开发,我想你会很清楚的知道SQL编程是很复杂的,先抛开嵌入语句,动态执行,高级函数,表达试等这些不谈单就解决性能问题就很头疼,下面就性能问题给出一些解决放案.(以下程序均在NT+SP6 SQL SERVER 7下调试通过)

一,存储过程
  我的一个朋友用VC/SQL SERVER做C/S项目开发,再开发过程中他的程序虽顺利执行,但遇到了由于需要大批量插入数据而引出的性能问题。他找到了我,虽然我没有用过VC但很明显在他程序中看出是在前台用循环操作象后台插入数据。这种方法再处理大批量数时无疑是不可取的,因编译器并不会处理SQL语句而是通过ODBC传输到后台,再在后台解释执行。
  由此可见经过以上几步性能问题以大打折扣,后我将他的程序段改为后台SQL编程,用存储过程实现。然后在前台用VC调用,这样一来问题以得到完美的解决。改后程序如下:(遇到此类问题的朋友可参考解决)

CREATE PROC usp_insert_temp
@iCount VARCHAR(10),
@Text VARCHAR(50),
@price VARCHAR(15)

AS

DECLARE @iIndex INT
DECLARE @pMoney FLOAT

SET @iIndex=CONVERT(INT,@iCount)
SET @pMoney=CONVERT(FLOAT,@price)

BEGIN TRAN
SELECT rygl_id,title,price
INTO rygl_temp FROM rqk
WHERE EXISTS
(SELECT rygl_id
FROM rygl
WHERE rqk.rygl_id=rygl.rygl_id
AND qty<30)
ORDER BY title_id

IF @@ERROR<>0
ROLLBACK TRAN
ELSE
COMMIT TRAN

WHILE @iIndex>0
BEGIN
BEGIN TRAN
SET @pMoney=@pMoney+1.1111
INSERT INTO rygl_temp(rygl_id,title,price)
VALUES(@iIndex,@Text,CONVERT(SMALLMONEY,@pMoney))

IF @@ERROR<>0 OR @@ROWCOUNT=0
ROLLBACK TRAN
ELSE
COMMIT TRAN
SET @iIndex=@iIndex-1
END

二,索引测试,比较
  合理的索引建立,运用可很大幅度提高程序性能,以下是在工作当中得出的经验,与大家共享。

1,ORDER BY和GROPU BY
  如果用户经常选择数据和使用ORDER BY和GROUP BY短语,任何一种索引都有助于SELECT的性能提高。如果用户选择的是顾客并按其姓名分类,两种索引都能快速检索数据。但下面的一些因素会使用户选择使用某一种索引。

2,返回范围内的数据
  列如,如果拥护希望返回在SMITH和TALBERT之间的所有顾客姓名,或者返回在日期“11/1/98”和“11/30/98”之间的订货量,并且用户经常做这类事情,那么最好在该范围所在的指定列使用聚类索引。因聚类索引已包含了经过分类排序的数据,这对于在指定范围内检索数据更为有效。聚类索引只需找到要检索的所有数据中的开头和结尾数据即可;而不象非聚类索,必须在数据层专查找来字叶层的每一个数据项。

3,列中有一个或极少的不同值
  在用户表中的某些列中喊有极少不同值,列如状态列中只包含INACVTIVE,ACVIVE或者TERMINATED。在这种情况下,在该列上使用任何类型索引都是不明智的,原因很简单:如果用户表包含了1500行大概有三分之一的行即500行在状态列中含有ACTIVE。扫描整个表,如果不是更高效,至少也是同先在索引页面中查找每个数据项而后寻找到包含ACTIVE状态的行所在的数
据页面也相同的效率。下面这个列子创建了一个表,它在有很很多重复值的列上进行索引,而该列具有很少的不同值。运行该脚本可能要花几分钟。

*/

DROP TABLE IndexTestTable
CREATE TABLE IndexTestTable
(
Tid INT IDENTITY(1,1) NOT NULL,
Status CHAR(10) NULL
)

GO

SET IDENTITY_INSERT IndexTestTable ON
DECLARE @intCount INT

BEGIN TRAN
SET @intCount=1
WHILE @intCount<=1500
BEGIN
INSERT IndexTestTable(Tid,Status) VALUES(@intCount,'Active')
SET @intCount=@intCount+3
END

SET @intCount=2
WHILE @intCount<=1500
BEGIN
INSERT IndexTestTable(Tid,Status) VALUES(@intCount,'inactive')
SET @intCount=@intCount+3
END

SET @intCount=3
WHILE @intCount<=1500
BEGIN
INSERT IndexTestTable(Tid,Status) VALUES(@intCount,'Terminated')
SET @intCount=@intCount+3
END
COMMIT TRAN

SET IDENTITY_INSERT IndexTestTable OFF
GO

DUMP TRANSACTION pubs WITH NO_LOG
GO

CREATE INDEX inTableUniquesStatus
ON IndexTestTable(Status)
GO

--不用索引查询
SELECT *
FROM IndexTestTable WITH(index(0))
WHERE Status='inactive'

--用索引查询
SELECT *
FROM IndexTestTable WITH(index(inTableUniquesStatus))
WHERE Status='inactive'

/*

  选中SHOW STATS I/O查看运行结果会另人吃惊。第一个SELECT语句引起全表扫描几乎不需要内存操作(因为只是进行插入,所有所有数据都在内存中,并不需要进行磁盘或物理读操作)。第二个SELECT语句则需要执行500个读操作,这就证实了我们所说的在这种情况下,使用任何类型索引都是不明智的。

4,
  以上举列说明了在何种情况下不应使用索引,现在咱们再反过来看看当索引列中
不同数目值增加时即有较少不同值时会怎样?见如下代码

*/

DROP TABLE IndexTestTable
GO

CREATE TABLE IndexTestTable
(
Tid INT IDENTITY(1,1) NOT NULL,
Status CHAR(10) NULL,
Co3 CHAR(20) NOT NULL,
Co4 CHAR(50) NOT NULL
)
GO

DECLARE @intNum INT
SET @intNum=0

BEGIN TRAN
WHILE @intNum<=1300
BEGIN
INSERT indexTestTable
VALUES(CHAR(@intNum %26 +65),'test3','test4')
SET @intNum=@intNum+1
END
COMMIT TRAN
GO

--不用索引查询
SELECT * FROM IndexTestTable WHIT(INDEX(0))
WHERE Status='B'

--创建聚集索引
CREATE CLUSTERED INDEX icIndexTestTable
ON IndexTestTable(Status)
GO

--使用索引查询
SELECT * FROM IndexTestTable WITH(INDEX(icIndexTestTable))
WHERE Status='B'

/*

5,
  用户很明显地能看出,随着表中行的数目和列中不同值的增长。使用索引可以较大幅度提高效率,由此又引出另一个问题,在何种情况下用何种索引更有效?上面列子已经介绍了聚类索引,大家都能看出在对于有较少不同植时使用聚类索引是有很大帮助的,但当不同值的数木增加并达到表中行的树木时则应该选非聚类索引。此时使用非聚类索在读操作上和聚类似索引并无
二异,但在对表进行写操作上的性能却提高不少,如果用户经常从表中的一个或少是数几个字段中检索数据,当非聚集索引包含要检索的所有字段时就会减少所需的读操作,如果不是那么正如上面第二条所说使用非聚集索引通常是钟很差的选择,下面这个列子说明了在何时应该使用聚集索引

*/

DROP TABLE IndexTestTable
GO

CREATE TABLE IndexTestTable
(
Tid INT IDENTITY(1,1)NOT NULL,
Status CHAR(20) NOT NULL
)
GO

DECLARE @intCount INT
SET @intCount=0

BEGIN TRAN
WHILE @intCount<=500
BEGIN
INSERT INTO IndexTestTable(Status) VALUES('test'+CONVERT(CHAR(6),@intCount))
SET @intCount=@intCount+1
END
COMMIT TRAN
GO

--创建聚集索引
CREATE CLUSTERED INDEX icIndexTestTable
ON IndexTestTable(Tid)
GO

--创建非聚集索引
CREATE INDEX inIndexTestTable
ON IndexTestTable(Tid)
GO

--使用非聚集索引查询
SELECT Tid FROM IndexTestTable WITH(INDEX(inIndexTestTable))
WHERE Tid BETWEEN 100 AND 500

--使用聚集索引查询
SELECT Tid FROM IndexTestTable WITH(INDEX(icIndexTestTable))
WHERE Tid BETWEEN 100 AND 500

/*

  集索引包含绝大多数的检索数据,则只需要读取很少的数据页这种情况下非聚集索引要比聚集索引好,如果表的数据行很庞大效果会更加明显。

6,
  要说明的是,索引虽有助于提高性能但不是索引越多越好,恰好相反过多的索引会导致系统低效。用户在表中每加进一个索引,维护索引集合就要做相应的更新工作。


2003-11-25 11:49:45   SQL Server日期计算   通常,你需要获得当前日期和计算一些其他的日期,例如,你的程序可能需要判断一个月的第一天或者最后一天。你们大部分人大概都知道怎样把日期进行分割(年、月、日等),然后仅仅用分割出来的年、月、日等放在几个函数中计算出自己所需要的日期!在这篇文章里,我将告诉你如何使用DATEADD和DATEDIFF函数来计算出在你的程序中可能你要用到的一些不同日期。
在使用本文中的例子之前,你必须注意以下的问题。大部分可能不是所有例子在不同的机器上执行的结果可能不一样,这完全由哪一天是一个星期的第一天这个设置决定。第一天(DATEFIRST)设定决定了你的系统使用哪一天作为一周的第一天。所有以下的例子都是以星期天作为一周的第一天来建立,也就是第一天设置为7。假如你的第一天设置不一样,你可能需要调整这些例子,使它和不同的第一天设置相符合。你可以通过@@DATEFIRST函数来检查第一天设置。

  为了理解这些例子,我们先复习一下DATEDIFF和DATEADD函数。DATEDIFF函数计算两个日期之间的小时、天、周、月、年等时间间隔总数。DATEADD函数计算一个日期通过给时间间隔加减来获得一个新的日期。要了解更多的DATEDIFF和DATEADD函数以及时间间隔可以阅读微软联机帮助。

  使用DATEDIFF和DATEADD函数来计算日期,和本来从当前日期转换到你需要的日期的考虑方法有点不同。你必须从时间间隔这个方面来考虑。比如,从当前日期到你要得到的日期之间有多少时间间隔,或者,从今天到某一天(比如1900-1-1)之间有多少时间间隔,等等。理解怎样着眼于时间间隔有助于你轻松的理解我的不同的日期计算例子。

【一个月的第一天】
  第一个例子,我将告诉你如何从当前日期去这个月的最后一天。请注意:这个例子以及这篇文章中的其他例子都将只使用DATEDIFF和DATEADD函数来计算我们想要的日期。每一个例子都将通过计算但前的时间间隔,然后进行加减来得到想要计算的日期。

  这是计算一个月第一天的SQL 脚本:
  SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0)

  我们把这个语句分开来看看它是如何工作的。最核心的函数是getdate(),大部分人都知道这个是返回当前的日期和时间的函数。下一个执行的函数DATEDIFF(mm,0,getdate())是计算当前日期和“1900-01-01 00:00:00.000”这个日期之间的月数。记住:时期和时间变量和毫秒一样是从“1900-01-01 00:00:00.000”开始计算的。这就是为什么你可以在DATEDIFF函数中指定第一个时间表达式为“0”。下一个函数是DATEADD,增加当前日期到“1900-01-01”的月数。通过增加预定义的日期“1900-01-01”和当前日期的月数,我们可以获得这个月的第一天。另外,计算出来的日期的时间部分将会是“00:00:00.000”。

  这个计算的技巧是先计算当前日期到“1900-01-01”的时间间隔数,然后把它加到“1900-01-01”上来获得特殊的日期,这个技巧可以用来计算很多不同的日期。下一个例子也是用这个技巧从当前日期来产生不同的日期。

【本周的星期一】
  这里我是用周(wk)的时间间隔来计算哪一天是本周的星期一。
  SELECT DATEADD(wk, DATEDIFF(wk,0,getdate()), 0)

【一年的第一天】
  现在用年(yy)的时间间隔来显示这一年的第一天。
  SELECT DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)

【季度的第一天】
  假如你要计算这个季度的第一天,这个例子告诉你该如何做。
  SELECT DATEADD(qq, DATEDIFF(qq,0,getdate()), 0)

【当天的半夜】
  曾经需要通过getdate()函数为了返回时间值截掉时间部分,就会考虑到当前日期是不是在半夜。假如这样,这个例子使用DATEDIFF和DATEADD函数来获得半夜的时间点。
  SELECT DATEADD(dd, DATEDIFF(dd,0,getdate()), 0)

【深入DATEDIFF和DATEADD函数计算】
  你可以明白,通过使用简单的DATEDIFF和DATEADD函数计算,你可以发现很多不同的可能有意义的日期。

  目前为止的所有例子只是仅仅计算当前的时间和“1900-01-01”之间的时间间隔数量,然后把它加到“1900-01-01”的时间间隔上来计算出日期。假定你修改时间间隔的数量,或者使用不同的时间间隔来调用DATEADD函数,或者减去时间间隔而不是增加,那么通过这些小的调整你可以发现和多不同的日期。

  这里有四个例子使用另外一个DATEADD函数来计算最后一天来分别替换DATEADD函数前后两个时间间隔。

【上个月的最后一天】
  这是一个计算上个月最后一天的例子。它通过从一个月的最后一天这个例子上减去3毫秒来获得。有一点要记住,在Sql Server中时间是精确到3毫秒。这就是为什么我需要减去3毫秒来获得我要的日期和时间。
  SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(mm,0,getdate()), 0))

  计算出来的日期的时间部分包含了一个Sql Server可以记录的一天的最后时刻(“23:59:59:997”)的时间。

【去年的最后一天】
  连接上面的例子,为了要得到去年的最后一天,你需要在今年的第一天上减去3毫秒。
  SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0))

【本月的最后一天】
  现在,为了获得本月的最后一天,我需要稍微修改一下获得上个月的最后一天的语句。修改需要给用DATEDIFF比较当前日期和“1900-01-01”返回的时间间隔上加1。通过加1个月,我计算出下个月的第一天,然后减去3毫秒,这样就计算出了这个月的最后一天。这是计算本月最后一天的SQL脚本。
  SELECT dateadd(ms,-3,DATEADD(mm, DATEDIFF(m,0,getdate())+1, 0))

【本年的最后一天】
  你现在应该掌握这个的做法,这是计算本年最后一天脚本
  SELECT dateadd(ms,-3,DATEADD(yy, DATEDIFF(yy,0,getdate())+1, 0))。

【本月的第一个星期一】
  好了,现在是最后一个例子。这里我要计算这个月的第一个星期一。这是计算的脚本。
  select DATEADD(wk, DATEDIFF(wk,0,dateadd(dd,6-datepart(day,getdate()),getdate())), 0)        
  在这个例子里,我使用了“本周的星期一”的脚本,并作了一点点修改。修改的部分是把原来脚本中“getdate()”部分替换成计算本月的第6天,在计算中用本月的第6天来替换当前日期使得计算可以获得这个月的第一个星期一。

【总结】
  我希望这些例子可以在你用DATEADD和DATEDIFF函数计算日期时给你一点启发。通过使用这个计算日期的时间间隔的数学方法,我发现为了显示两个日期之间间隔的有用历法是有价值的。注意,这只是计算出这些日期的一种方法。要牢记,还有很多方法可以得到相同的计算结果。假如你有其他的方法,那很不错,要是你没有,我希望这些例子可以给你一些启发,当你要用DATEADD和DATEDIFF函数计算你程序可能要用到的日期时。


2003-11-25 12:11:33     在数据库管理系统中,查询是一项必不可少的功能。查询功能是直接体现系统功能的一项重要指标。查询的方式主要有以下几种:1固定字段的单一查询;2可选择字段的单一查询;3限制若干个字段的多重查询;4可任意选择字段的多重查询。前两种也称为单条件查询,后两种称为多重(或多条件)查询。在实际中,系统(实为程序员)提供给用户的查询方式以单条件查询为多,即使提供了多条件方式,通常也只有两或三个条件,因为编写多重查询是一项非常棘手且繁琐的事情。仅为此,程序员吃尽了苦头。实际上,利用表格Grid功能,就能轻松地实现多重查询。本人以Delphi为例,介绍具体的实现方法,但这种思想,也同样适合于其它的编程语言(如Visual Foxpro)。

  另外,为使程序方便“移植”, 本人把各功能模块化,使其更具有通用性。

程序主要按如下三个功能来实现:
①设置DBGrid
②生成查询条件(语句)
③执行查询

具体步骤如下:
⑴新建一工程文件,取名为PDBGrid.dpr;
⑵给单元文件取名为UDBGrid.pas,在其相应的表单(取名为frmDBGrid)中添加如下控件并编写相应的代码:

控件名称
主要属性及值
备注
Table1
DataBaseName(MyAlias)
TableName
(MyTable1.db)
Active
(false)
查询对象:数据集
MyTable1.db为任意的表
DataSource1
DataSet(Table1)

DBGrid1
DataSource(DataSource1)

显示数据源
Table2
DataBaseName(MyAlias)
TableName
(CxComm.db)
Active
(false)

记录查询条件的数据集
(CxComm.db结构下述)
DataSource2
DataSet(Table2)

DBGrid2
DataSource(DataSource2)

提供查询处理
Query1
DataBaseName(MyAlias)
Active
(false)

保存和执行SQL语句的数据集
DataSource3
DataSet
(Query 1)

DGrid3
DataSource
(DataSource3)

显示查询结果
Memo1
Lines(<动态赋值>)

显示及修改SQL语句
Button1
Caption(设置DBGrid)

Click事件下述
Button2
Caption(生成查询)

Click事件下述
Button3
Caption(执行查询)

Click事件下述

其中
Table2(记录查询条件的数据集)对应的表CxComm.db的结构定义如下:

字段名
项目
关系
实例
逻辑
类型
A(字符型)
A(字符型)
A(字符型)
A(字符型)
大小
14
5
10
6

表单的FormActivate事件代码如下:
procedure TfrmDBGrid.FormActivate(Sender: TObject);
begin
if Table2.Active then Table2.Close;
Table2.EmptyTable; //清空条件
Table1.Open;
Table2.Open;
end;

Button1(设置DBGrid)的Click事件代码如下:
procedure TfrmDBGrid.Button1Click(Sender: TObject);
begin
MySetDBGrid(Table1,DBGrid2); // MySetDBGrid为自定义过程
                    //以Table1为数据源,DBGrid2为记录筛选(查询)条件的表格
end;

Button2(生成查询)的Click事件代码如下:
procedure TfrmDBGrid.Button2Click(Sender: TObject);
begin
if MyCreate_SQL(Table1,Table2,Query1) //MyCreate_SQL为自定义函数
                          //由指定数据来源表来生成SQL,存入Query1
then begin
  Memo1.Lines.Clear;
  Memo1.Lines:=(Query1.SQL);
  Memo1.Modified:=false;
end
end;

Button3(执行查询)的Click事件代码如下:
procedure TfrmDBGrid.Button3Click(Sender: TObject);
begin
with Query1,SQL do
begin
  Close;
  if Memo1.Modified //用户可修改SQL语句
  then SQL:=Memo1.Lines;
  try
    ExecSQL;
    Open;
  except //捕捉错误并处理
    begin
    MessageBeep(0);
    Application.MessageBox('错误的SQL语句!','确认',MB_OK+MB_ICONSTOP);
    Close;
    end;
  end //try
end;
end; //执行SQL

自定义过程MySetDBGrid (设置DBGrid)的代码如下:
procedure TfrmDBGrid.MySetDBGrid(sTable:TTable;tjDBGrid:TDBGrid);
//参数说明:sTable为数据(包括字段,记录)来源表
// tjDBGrid为记录筛选(查询)条件的表格
var i:byte;
begin
//设置查询项目
if not sTable.Active then sTable.Open;
tjDBGrid.Columns[0].PickList.Clear;
for i:=0 to sTable.FieldCount-1 do //记录数(即字段数)
begin
  tjDBGrid.Columns[0].PickList.Add(sTable.Fields.FieldName);
end; //for
//设置关系(=,<>,>,>=,<,<=) 及逻辑(AND,OR)
tjDBGrid.Columns[1].PickList.Text:='='+#13+'<>'+#13+'>'+#13+'>='+#13+'<'+#13+'<=';
tjDBGrid.Columns[3].PickList.Text:='AND'+#13+'OR';
end;//设置DBGrid

自定义函数MyCreate_SQL (生成查询)的代码如下:
function TfrmDBGrid.MyCreate_SQL(sTable,tjTable:TTable;tjQuery:TQuery):boolean;
//参数说明:sTable为数据(包括字段,记录)来源表
// tjTable为记录筛选(查询)条件的表
// tjQuery记录SQL语句
var i:byte;
  lsDate:TDate; //检测日期格式用
  sLj,sFilter,sFieldName:string; //分别表示:逻辑关系,筛选条件,字段名
begin
Result:=true;
//生成"筛选条件"语句
with tjQuery,SQL do
begin
  Close;
  Clear;
  DatabaseName:=sTable.DatabaseName; //设置Query1的别名
  Add('Select * from '''+sTable.TableName+'''');
end;
with tjTable do //查询(筛选)条件表
begin
  if not Active then Open;
  if IsEmpty
  then begin
    Application.MessageBox('未选择筛选条件!','确定',MB_OK+MB_ICONEXCLAMATION);
    Exit;
  end;
  tjQuery.SQL.Add(' Where ');//含有筛选条件
  sFilter:=''; //临时记录筛选条件
  First;
  for i:=0 to RecordCount-1 do
  begin
    sLj:=Fields[3].AsString; //逻辑关系AND,OR
    //(字段名0>1实际值2)
    sFilter:=sFilter+'(';
    sFilter:=sFilter+Fields[0].AsString+Fields[1].AsString;
    sFieldName:=Fields[0].AsString; //取第1列的字段名
    case Table1.FieldByName(sFieldName).DataType of ftString:
    begin //字符型处理
    sFilter:=sFilter+''''+Fields[2].AsString+'''' //第2列为关系
    end;
    ftFloat, //浮点型处理
    ftAutoInc, //自增型
    ftSmallInt, //短整型
    ftInteger, //整型
    ftCurrency: begin //货币型
    sFilter:=sFilter+Fields[2].AsString;
  end;
  ftDate:
    begin //日期型处理
    try
      lsDate:=StrToDate(Fields[2].AsString);
      sFilter:=sFilter+''''+FormatDateTime('mm/dd/yyyy',StrToDate(Fields[2].AsString))+'''';
    except
      Application.MessageBox('错误的日期格式!','确认',MB_OK+MB_ICONSTOP);
      Result:=false; //返回错误标志
      break;
    end;//try 日期格式判断
    end;
    //此处可增加对其它类型数据的处理
    end;//case
    sFilter:=sFilter+')';
    if sLj<>''
    then begin
    if RecNo<>RecordCount //且"非最后行"的记录
    then sFilter:=sFilter+Fields[3].AsString; //And|Or;
    end
    else break;
    Next
  end;
end; //not IsEmpty(筛选)非空
tjQuery.SQL.Add(sFilter); //保存查询条件
end; //处理筛选条件

另外,需要进行如下说明:
...
Type
...
procedure MySetDBGrid(sTable:TTable;tjDBGrid:TDBGrid);
function MyCreate_SQL(sTable,tjTable:TTable;tjQuery:TQuery):boolean;
private
{ Private declarations }
...

  值得说明的是,⑴为从一定程序上简化程序,逻辑关系只提供了AND和OR两种,但为允许用户修改SQL语句,如:在多条件之间增加括号来改变运算顺序等,使得查询功能更加强大,因此增加了Memo控件;⑵在实际系统中,为方便用户的操作,可增加几个Button(按钮),功能分别是对Table2的“增加”、“删除”,这样用户界面会更友好些。
利用这种方法来设置查询,条件个数是无限制的,且在屏幕上不会占据太大的空间,程序员实现起来要简单得多了。

软件环境:中文Win98/中文Delphi5.0。


2003-11-25 12:39:56   有关重复记录的删除   有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如Name字段重复,而其他字段不一定重复或都重复可以忽略。

1、对于第一种重复,比较容易解决,使用
  select distinct * from tableName
就可以得到无重复记录的结果集。
  如果该表需要删除重复的记录(重复记录保留1条),可以按以下方法删除
  select distinct * into #Tmp from tableName
  drop table tableName
  select * into tableName from #Tmp
  drop table #Tmp
发生这种重复的原因是表设计不周产生的,增加唯一索引列即可解决。

2、这类重复问题通常要求保留重复记录中的第一条记录,操作方法如下假设有重复的字段为Name,Address,要求得到这两个字段唯一的结果集
  select identity(int,1,1) as autoID, * into #Tmp from tableName
  select min(autoID) as autoID into #Tmp2 from #Tmp group by Name,autoID
  select * from #Tmp where autoID in(select autoID from #tmp2)
最后一个select即得到了Name,Address不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)


2003-11-25 13:15:26   SQL SERVER 2000 数据库备份与恢复单元unit BackRestoreSQLDB;
{描述:SQL SERVER 2000 数据库备份与恢复单元 ,本单元函数在SQL SERVER 2000 +Delphi7.0编译通过
时间:2003.09.15
作者:chenshaizi
}
interface

uses
adodb, db;
function repl_substr(sub_old, sub_new, s: string): string; //把sub_old换成sub_new,后面有用。
function BackupSQLDataBase(connstr_sql, DatabaseName, Backup_FileName: string): Boolean; //数据库备份函数
//SQL数据数据库备份,connstr_sql是ADO控件的connectionstring,DatabaseName是数据库名称,
//Backup_FileName要备份到的目 标文件
function RestoreSQLDataBase(connstr_sql, DatabaseName, Restore_FileName: string): Boolean; //数据库恢复函数
//Restore_FileName以前备份的数据库文件,
implementation

function repl_substr(sub_old, sub_new, s: string): string;
var
i: integer;
begin
repeat
  i := pos(sub_old, s);
  if i > 0 then
  begin
    delete(s, i, Length(sub_old));
    insert(sub_new, s, i);
  end;
until i < 1;
Result := s;
end;

function BackupSQLDataBase(connstr_sql, DatabaseName, Backup_FileName: string): Boolean;
var
//备份SQL数据库SQL数据数据库备份,connstr_sql是ADO控件的connectionstring,DatabaseName是数据库名称,
//Backup_FileName要备份到的目标文件
aADOQuery: TADOQuery;
begin
try
  aADOQuery := TADOQuery.Create(nil);
  aADOQuery.Close;
  aADOQuery.ConnectionString := connstr_sql;
  aADOQuery.SQL.Clear;
  aADOQuery.SQL.Add('backup database ' + DatabaseName + ' to disk = ' + '''' + Backup_FileName + ''' with format');
  try
    aADOQuery.ExecSQL;
    Result := true;
  except
    Result := false;
    exit;
  end;
finally
  aADOQuery.Free;
end;
end;

function RestoreSQLDataBase(connstr_sql, DatabaseName, Restore_FileName: string): Boolean;
var //数据库恢复函数,estore_FileName以前备份的数据库文件
aADOQuery: TADOQuery;
begin
try
  aADOQuery := TADOQuery.Create(nil);
  aADOQuery.Close; //恢复数据库不能打开数据库,要打开系统数据库master,把连接字符串如adoconnetion的connectionstring中的数据库名称换成"master"数据库
  aADOQuery.ConnectionString := repl_substr(DatabaseName, 'master', connstr_sql);
  aADOQuery.SQL.Clear;
  aADOQuery.SQL.Add('RESTORE DATABASE ' + DatabaseName + ' from disk = ' + '''' + Restore_FileName + '''');
  try
    aADOQuery.ExecSQL;
    Result := true;
  except
    Result := false;
    exit;
  end;
finally
  aADOQuery.Free;
end;
end;
end.


2003-11-25 13:17:15   不用控件,通过ADO对象连接sqlserver数据库关键词:ADO连接sqlserver数据库

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,comobj, Db, ADODB;

//要伸明comobj 下面为连接代码:

var
adoc,ador:variant;
begin
adoc:=createoleobject('adodb.connection');
adoc.open('Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=customer;Data Source=BERN');
ador:=createoleobject('adodb.recordset');
ador.activeconnection:=adoc;
ador.CursorType:=ctDynamic;
ador.open('select * from t_customer',adoc);  
end;


2003-11-25 13:28:58   存取JPEG文件到SQLSERVER数据库【王大川(WDCZZH)】【关键词】:JPEG图片图像数据库
  最近在CSDN上看到两篇关于《DELPHI中存取JPEG文件到SQLSERVER》中的文章之后,觉得其中讲述的方法虽然有可取之处,但颇费时,我这里有更简单的操作方法,而且安全可靠,不敢一人独享,愿发布出来与大家共享。在Delphi7.0+Win2000+SqlServer 2000中测试通过,运行良好,现将思路、源码公开如下:

【解决思路】:
1、 关键在于将打开的JPEG文件动态转换为Tbitmap对象并显示在Timage对象中;
2、 将显示的图片提交到数据库中。

本例中在SQLSERVER2000中建立了一个试例表:exam(xm char(10),photo image);
程序源代码:

unit SavePic;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtDlgs, ExtCtrls, DBCtrls, Grids, DBGrids, DB, ADODB, Buttons, StdCtrls,Jpeg;

type
TForm1 = class(TForm)
  SpeedButton1: TSpeedButton;
  ADOConnection1: TADOConnection;
  Table1: TADOTable;
  DataSource1: TDataSource;
  DBGrid1: TDBGrid;
  DBImage1: TDBImage;
  Image1: TImage;
  SpeedButton2: TSpeedButton;
  OpenPictureDialog1: TOpenPictureDialog;
  Label1: TLabel;
  Label2: TLabel;
  Edit1: TEdit;
  SpeedButton3: TSpeedButton;
  procedure SpeedButton2Click(Sender: TObject);
  procedure SpeedButton1Click(Sender: TObject);
  procedure SpeedButton3Click(Sender: TObject);
private
  { Private declarations }
public
  { Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.SpeedButton2Click(Sender: TObject);
var
bmp1:TBitmap;
jpg1:TJpegImage;
begin
OpenPictureDialog1.DefaultExt:=GraphicExtension(TJpegimage);
if OpenPictureDialog1.Execute then
begin
  bmp1:=TBitmap.Create;
  jpg1:=TJpegImage.Create;
  try
    jpg1.LoadFromFile(OpenPictureDialog1.FileName);
    bmp1.Assign(jpg1);
    Image1.Picture.Bitmap.Assign(bmp1);
  finally
    jpg1.Free;
    bmp1.Free;
  end;
end;
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
begin
table1.Open;
table1.insert;
table1.fieldbyname('xm').asstring:=Edit1.Text;
table1.FieldByName('photo').Assign(Image1.Picture);
tabl
 

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/guolei0451/archive/2006/09/13/1217574.aspx

你可能感兴趣的:(数据库,sql,table,sql,server,数据库,insert,null)