SQL Server 知识

 

sql server日志文件总结及日志满的处理办法

交易日志(Transaction logs)是数据库结构中非常重要但又经常被忽略的部分。由于它并不像数据库中的schema那样活跃,因此很少有人关注交易日志。

交易日志是针对数据库改变所做的记录,它可以记录针对数据库的任何操作,并将记录结果保存在独立的文件中。对于任何每一个交易过程,交易日志都有非常全面的记录,根据这些记录可以将数据文件恢复成交易前的状态。从交易动作开始,交易日志就处于记录状态,交易过程中对数据库的任何操作都在记录范围,直到用户点击提交或后退后才结束记录。每个数据库都拥有至少一个交易日志以及一个数据文件。

出于性能上的考虑,SQL Server将用户的改动存入缓存中,这些改变会立即写入交易日志,但不会立即写入数据文件。交易日志会通过一个标记点来确定某个交易是否已将缓存中的数据写入数据文件。当SQL Server重启后,它会查看日志中最新的标记点,并将这个标记点后面的交易记录抹去,因为这些交易记录并没有真正的将缓存中的数据写入数据文件。这可以防止那些中断的交易修改数据文件。
  

维护交易日志

因为很多人经常遗忘交易日志,因此它也会给系统带来一些问题。随着系统的不断运行,日志记录的内容会越来越多,日志文件的体积也会越来越大,最终导致可用磁盘空间不足。除非日常工作中经常对日志进行清理,否则日志文件最终会侵占分区内的全部可用空间。日志的默认配置为不限容量,如果以这种配置工作,它就会不断膨胀,最终也会占据全部可用空间。这两种情况都会导致数据库停止工作。

对交易日志的日常备份工作可以有效的防止日志文件过分消耗磁盘空间。备份过程会将日志中不再需要的部分截除。截除的方法是首先把旧记录标记为非活动状态,然后将新日志覆盖到旧日志的位置上,这样就可以防止交易日志的体积不断膨胀。如果无法对日志进行经常性的备份工作,最好将数据库设置为"简单恢复模式"。在这种模式下,系统会强制交易日志在每次记录标记点时,自动进行截除操作,以新日志覆盖旧日志。

截除过程发生在备份或将旧标记点标为非活动状态时,它使得旧的交易记录可以被覆盖,但这并不会减少交易日志实际占用的磁盘空间。就算不再使用日志,它依然会占据一定的空间。因此在维护时,还需要对交易日志进行压缩。压缩交易日志的方法是删除非活动记录,从而减少日志文件所占用的物理硬盘空间。

通过使用DBCC SHRINKDATABASE语句可以压缩当前数据库的交易日志文件,DBCC SHRINKFILE语句用来压缩指定的交易日志文件,另外也可以在数据库中激活自动压缩操作。当压缩日志时,首先会将旧记录标记为非活动状态,然后将带有非活动标记的记录彻底删除。根据所使用的压缩方式的不同,你可能不会立即看到结果。在理想情况下,压缩工作应该选在系统不是非常繁忙的时段进行,否则有可能影响数据库性能。

恢复数据库

交易记录备份可以用来将数据库恢复到某一指定状态,但交易记录备份本身不足以完成恢复数据库的任务,还需要备份的数据文件参与恢复工作。恢复数据库时,首先进行的是数据文件的恢复工作。在整个数据文件恢复完成前,不要将其设为完成状态,否则交易日志就不会被恢复。当数据文件恢复完成,系统会通过交易日志的备份将数据库恢复成用户希望的状态。如果在数据库最后一次备份后,存在多个日志文件的备份,备份程序会按照它们建立的时间依次将其恢复。

另一种被称为log shipping的过程可以提供更强的数据库备份能力。当log shipping配置好后,它可以将数据库整个复制到另一台服务器上。在这种情况下,交易日志也会定期发送到备份服务器上供恢复数据使用。这使得服务器一直处于热备份状态,当数据发生改变时它也随之更新。另一个服务器被称作监视(monitor)服务器,可以用来监视按规定时间间隔发送的shipping信号。如果在规定时间内没有收到信号,监视服务器会将这一事件记录到事件日志。这种机制使得log shipping经常成为灾难恢复计划中使用的方案。

性能优化

交易日志对数据库有重要作用,同时它对系统的整体性能也有一定影响。通过几个选项,我们可以对交易日志的性能进行优化。由于交易日志是一个连续的磁盘写入过程,在这当中不会发生读取动作。因此将日志文件放在一个独立的磁盘,对优化性能有一定作用。

包括安装时提示有挂起的操作、收缩数据库、压缩数据库、转移数据库给新用户以已存在用户权限、检查备份集、修复数据库等 
 (一)挂起操作
在安装Sqlsp补丁的时候系统提示之前有挂起的安装操作,要求重启,这里往往重启无用,解决办法:
HKEY_LOCAL_MACHINE"SYSTEM"CurrentControlSet"Control"Session Manager
删除PendingFileRenameOperations

(二)收缩数据库
--
重建索引
DBCC REINDEX
DBCC INDEXDEFRAG
--
收缩数据和日志
DBCC SHRINKDB
DBCC SHRINKFILE

三)压缩数据库
dbcc shrinkdatabase(dbname)

(四)转移数据库给新用户以已存在用户权限
exec sp_change_users_login 'update_one','newname','oldname'
go

(五)检查备份集
RESTORE VERIFYONLY from disk='E:"dvbbs.bak'

(六)修复数据库
ALTER DATABASE [dvbbs] SET SINGLE_USER
GO
DBCC CHECKDB('dvbbs',repair_allow_data_loss) WITH TABLOCK
GO
ALTER DATABASE [dvbbs] SET MULTI_USER
GO


--REPAIR_ALLOW_DATA_LOSS
-- 
执行由 REPAIR_REBUILD 完成的所有修复,包括对行和页进行分配和取消分配以改正分配错误、结构行或页的错误,以及删除已损坏的文本对象。这些修复可能会导致一些数据丢失。修复操作可以在用户事务下完成以允许用户回滚所做的更改。如果回滚修复,则数据库仍会含有错误,应该从备份进行恢复。如果由于所提供修复等级的缘故遗漏某个错误的修复,则将遗漏任何取决于该修复的修复。修复完成后,备份数据库。
--REPAIR_FAST
进行小的、不耗时的修复操作,如修复非聚集索引中的附加键。这些修复可以很快完成,并且不会有丢失数据的危险。
--REPAIR_REBUILD
执行由 REPAIR_FAST 完成的所有修复,包括需要较长时间的修复(如重建索引)。执行这些修复时不会有丢失数据的危险。

--DBCC CHECKDB('dvbbs') with NO_INFOMSGS,PHYSICAL_ONLY

SQL SERVER日志清除的两种方法
在使用过程中大家经常碰到数据库日志非常大的情况,在这里介绍了两种处理方法……

方法一

一般情况下,SQL数据库的收缩并不能很大程度上减小数据库大小,其主要作用是收缩日志大小,应当定期进行此操作以免数据库日志过大
1
、设置数据库模式为简单模式:打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server-->SQL Server-->双击打开你的服务器-->双击打开数据库目录-->选择你的数据库名称(如论坛数据库Forum-->然后点击右键选择属性-->选择选项-->在故障还原的模式中选择简单,然后按确定保存
2
、在当前数据库上点右键,看所有任务中的收缩数据库,一般里面的默认设置不用调整,直接点确定
3、收缩数据库完成后,建议将您的数据库属性重新设置为标准模式,操作方法同第一点,因为日志在一些异常情况下往往是恢复数据库的重要依据

方法二

SET NOCOUNT ON
DECLARE @LogicalFileName sysname,
        @MaxMinutes INT,
        @NewSize INT


USE     tablename             -- 要操作的数据库名
SELECT  @LogicalFileName = 'tablename_log',  --
日志文件名
@MaxMinutes = 10,               -- Limit on time allowed to wrap log.
        @NewSize = 1                  --
你想设定的日志文件的大小(M)

-- Setup / initialize
DECLARE @OriginalSize int
SELECT @OriginalSize = size
  FROM sysfiles
  WHERE name = @LogicalFileName
SELECT 'Original Size of ' + db_name() + ' LOG is ' +
        CONVERT(VARCHAR(30),@OriginalSize) + ' 8K pages or ' +
        CONVERT(VARCHAR(30),(@OriginalSize*8/1024)) + 'MB'
  FROM sysfiles
  WHERE name = @LogicalFileName
CREATE TABLE DummyTrans
  (DummyColumn char (8000) not null)


DECLARE @Counter   INT,
        @StartTime DATETIME,
        @TruncLog  VARCHAR(255)
SELECT  @StartTime = GETDATE(),
        @TruncLog = 'BACKUP LOG ' + db_name() + ' WITH TRUNCATE_ONLY'

DBCC SHRINKFILE (@LogicalFileName, @NewSize)
EXEC (@TruncLog)
-- Wrap the log if necessary.
WHILE     @MaxMinutes > DATEDIFF (mi, @StartTime, GETDATE()) -- time has not expired
      AND @OriginalSize = (SELECT size FROM sysfiles WHERE name = @LogicalFileName) 
      AND (@OriginalSize * 8 /1024) > @NewSize 
  BEGIN -- Outer loop.
    SELECT @Counter = 0
    WHILE  ((@Counter < @OriginalSize / 16) AND (@Counter < 50000))
      BEGIN -- update
        INSERT DummyTrans VALUES ('Fill Log') 
        DELETE DummyTrans
        SELECT @Counter = @Counter + 1
      END  
    EXEC (@TruncLog) 
  END  
SELECT 'Final Size of ' + db_name() + ' LOG is ' +
        CONVERT(VARCHAR(30),size) + ' 8K pages or ' +
        CONVERT(VARCHAR(30),(size*8/1024)) + 'MB'
  FROM sysfiles
  WHERE name = @LogicalFileName
DROP TABLE DummyTrans
SET NOCOUNT OFF

删除数据库中重复数据的几个方法
数据库的使用过程中由于程序方面的问题有时候会碰到重复数据,重复数据导致了数据库部分设置不能正确设置……

方法一

declare @max integer,@id integer
declare cur_rows cursor local for select
主字段,count(*) from 表名 group by 主字段 having count(*) > 1
open cur_rows
fetch cur_rows into @id,@max
while @@fetch_status=0
begin
select @max = @max -1
set rowcount @max
delete from
表名 where 主字段 = @id
fetch cur_rows into @id,@max
end
close cur_rows
set rowcount 0


方法二

有两个意义上的重复记录,一是完全重复的记录,也即所有字段均重复的记录,二是部分关键字段重复的记录,比如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即得到了NameAddress不重复的结果集(但多了一个autoID字段,实际写时可以写在select子句中省去此列)

更改数据库中表的所属用户的两个方法
大家可能会经常碰到一个数据库备份还原到另外一台机器结果导致所有的表都不能打开了,原因是建表的时候采用了当时的数据库用户……

--更改某个表
exec sp_changeobjectowner 'tablename','dbo'


--存储更改全部表
CREATE PROCEDURE dbo.User_ChangeObjectOwnerBatch
 @OldOwner as NVARCHAR(128),
 @NewOwner as NVARCHAR(128)
AS

DECLARE @Name   as NVARCHAR(128)
DECLARE @Owner  as NVARCHAR(128)
DECLARE @OwnerName  as NVARCHAR(128)

DECLARE curObject CURSOR FOR
 select 'Name'   = name,
  'Owner'   = user_name(uid)
 from sysobjects
 where user_name(uid)=@OldOwner
 order by name

OPEN  curObject
FETCH NEXT FROM curObject INTO @Name, @Owner
WHILE(@@FETCH_STATUS=0)
BEGIN     
 if @Owner=@OldOwner
 begin
  set @OwnerName = @OldOwner + '.' + rtrim(@Name)
  exec sp_changeobjectowner @OwnerName, @NewOwner
 end
-- select @name,@NewOwner,@OldOwner

 FETCH NEXT FROM curObject INTO @Name, @Owner
END

close curObject
deallocate curObject


GO


SQL SERVER中直接循环写入数据
没什么好说的了,大家自己看,有时候有点用处

declare @i int
set @i=1
while @i<30
begin
   insert into test (userid) values(@i)
   set @i=@i+1
end

无数据库日志文件恢复数据库方法两则
数据库日志文件的误删或别的原因引起数据库日志的损坏

方法一

1.新建一个同名的数据库

2.再停掉sql server(注意不要分离数据库)

3.用原数据库的数据文件覆盖掉这个新建的数据库

4.再重启sql server

5.此时打开企业管理器时会出现置疑,先不管,执行下面的语句(注意修改其中的数据库名)

6.完成后一般就可以访问数据库中的数据了,这时,数据库本身一般还要问题,解决办法是,利用
数据库的脚本创建一个新的数据库,并将数据导进去就行了.

USE MASTER
GO

SP_CONFIGURE 'ALLOW UPDATES',1 RECONFIGURE WITH OVERRIDE
GO

UPDATE SYSDATABASES SET STATUS =32768 WHERE NAME='置疑的数据库名'
Go

sp_dboption '置疑的数据库名', 'single user', 'true'
Go

DBCC CHECKDB('置疑的数据库名')
Go

update sysdatabases set status =28 where name='置疑的数据库名'
Go

sp_configure 'allow updates', 0 reconfigure with override
Go

sp_dboption '置疑的数据库名', 'single user', 'false'
Go

方法二

事情的起因
昨天,系统管理员告诉我,我们一个内部应用数据库所在的磁盘空间不足了。我注意到数据库事件日志文件XXX_Data.ldf文件已经增长到了3GB,于是我决意缩小这个日志文件。经过收缩数据库等操作未果后,我犯了一个自进入行业以来的最大最愚蠢的错误:竟然误删除了这个日志文件!后来我看到所有论及数据库恢复的文章上都说道:无论如何都要保证数据库日志文件存在,它至关重要,甚至微软甚至有一篇KB文章讲如何只靠日志文件恢复数据库的。我真是不知道我那时候是怎么想的?!

这下子坏了!这个数据库连不上了,企业管理器在它的旁边写着“(置疑)”。而且最要命的,这个数据库从来没有备份了。我唯一找得到的是迁移半年前的另外一个数据库服务器,应用倒是能用了,但是少了许多记录、表和存储过程。真希望这只是一场噩梦!

没有效果的恢复步骤
附加数据库
_Rambo
讲过被删除日志文件中不存在活动日志时,可以这么做来恢复:

1,分离被置疑的数据库,可以使用sp_detach_db
2
,附加数据库,可以使用sp_attach_single_file_db

但是,很遗憾,执行之后,SQL Server质疑数据文件和日志文件不符,所以无法附加数据库数据文件。

DTS数据导出
不行,无法读取XXX数据库,DTS Wizard报告说初始化上下文发生错误

紧急模式
怡红公子讲过没有日志用于恢复时,可以这么做:

1,把数据库设置为emergency mode

2,重新建立一个log文件

3,把SQL Server 重新启动一下

4,把应用数据库设置成单用户模式

5,做DBCC CHECKDB

6,如果没有什么大问题就可以把数据库状态改回去了,记得别忘了把系统表的修改选项关掉

我实践了一下,把应用数据库

重启SQL Server服务;

     运行以下语句,把应用数据库设置为Single User模式;

      运行“sp_dboption 'XXX', 'single user', 'true'”

执行结果:

      命令已成功完成。

ü         DBCC CHECKDB

      运行“DBCC CHECKDB('XXX')”

执行结果:

'XXX' DBCC 结果。

'sysobjects' DBCC 结果。

对象 'sysobjects' 273 行,这些行位于 5 页中。

'sysindexes' DBCC 结果。

对象 'sysindexes' 202 行,这些行位于 7 页中。

'syscolumns' DBCC 结果。

………

ü         运行以下语句把系统表的修改选项关掉;

      运行“sp_resetstatus "XXX"

go

sp_configure 'allow updates', 0

reconfigure with override

Go”

执行结果:

sysdatabases 中更新数据库 'XXX' 的条目之前,模式 = 0,状态 = 28(状态 suspect_bit = 0),

没有更新 sysdatabases 中的任何行,因为已正确地重置了模式和状态。没有错误,未进行任何更改。

DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。

已将配置选项 'allow updates' 1 改为 0。请运行 RECONFIGURE 语句以安装。

    重新建立另外一个数据库XXX.Lost

DTS导出向导
    
运行DTS导出向导;

     复制源选择EmergencyMode的数据库XXX,导入到XXX.Lost

        选择SQL Server数据库之间复制对象和数据,试了多次,好像不行,只是复制过来了所有表结构,但是没有数据,也没有视图和存储过程,而且DTS向导最后报告复制失败;

       所以最后选择从源数据库复制表和视图,但是后来发现,这样总是只能复制一部分表记录;

      于是选择用一条查询指定要传输的数据,缺哪个表记录,就导哪个;

        视图和存储过程是执行SQL语句添加的。

维护Sql Server中表的索引
在使用和创建数据库索引中经常会碰到一些问题,在这里可以采用一些另类的方法解决

--第一步:查看是否需要维护,查看扫描密度/Scan Density是否为100%
declare @table_id int
set @table_id=object_id('
表名')
dbcc showcontig(@table_id)

--第二步:重构表索引
dbcc dbreindex('
表名',pk_索引名,100)

--重做第一步,如发现扫描密度/Scan Density还是小于100%则重构表的所有索引
--
杨铮:并不一定能达100%
dbcc dbreindex('
表名','',100)

SQL Server补丁安装常见问题
谁碰到问题就看看咯:)

一、补丁安装过程中常见问题


如果在安装补丁的时候遇到如下类似错误:

1、安装过程中出现以前进行的程序创建了挂起的文件操作,运行安装程序前,必须重新启动,请按照下面步骤解决:

a、重启机器,再进行安装,如果发现还有该错误,请按下面步骤
b
、在开始->运行中输入regedit
c
、到HKEY_LOCAL_MACHINE"SYSTEM"CurrentControlSet"Control"Session Manager 位置
d
、选择文件->倒出,保存
e
、在右边窗口右击PendingFileRenameOperations,选择删除,然后确认
f
、重启安装,问题解决

如果还有同样问题,请检查其它注册表中是否有该值存在,如有请删掉

2、在安装SQL Server SP3,有时候会出现:无论用windows认证还是混和认证,都出现密码错误的情况,这时查看临时目录下的sqlsp.out,会发现以下描述:
[TCP/IP Sockets]Specified SQL server not found.
[TCP/IP Sockets]ConnectionOpen (Connect()).
其实这是SQL Server SP3的一个小bug,在安装sp3的时候,没有监听tcp/ip端口,可以按照以下步骤进行:

1、打开SQL server客户器网络实用工具和服务器网络工具,确保启用的协议中包含name pipe,并且位置在第一位.
2
、确保[HKEY_LOCAL_MACHINE"SOFTWARE"Microsoft"MSSQLServer"Client"ConnectTo]
"DSQUERY"="DBNETLIB".
如果没有,请自己建立
3
、停止mssql.
4
、进行安装.

这样就可以进行正确安装了

二、SQL Server补丁版本的检查

SQL Server的补丁版本检查不如Windows 补丁版本检查直接,一个系统管理员,如果不了解SQL Server版本对应的补丁号,可能也会遇到一点麻烦,因此在这说明一下,通过这样的办法判别机器是安全的办法,不会对系统产生任何影响。
1
、用Isql或者SQL查询分析器登录到SQL Server,如果是用Isql,请在cmd窗口输入isql -U sa,然后输入密码,进入;如果是用SQL查询分析器,请从程序中启动,输入sa和密码(也可以用windows验证)。
2
、在ISQL中输入:
Select @@Version

go

或者SQL查询分析器中输入(其实如果不想输入,只要打开帮助的关于就可以了 )
Select @@Version

然后按执行;
这时会返回SQL的版本信息,如下:
Microsoft SQL Server 2000 - 8.00.760 (Intel X86) Dec 17 2002 14:22:05 Copyright (c) 1988-2003 Microsoft Corporation Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 3)
其中的8.00.760就是SQL Server的版本和补丁号。对应关系如下:

8.00.194 ——————SQL Server 2000 RTM
8.00.384
——————(SP1)
8.00.534
——————(SP2)
8.00.760
——————(SP3)

这样我们就能看到SQL Server的正确版本和补丁号了。

我们也可以用xp_msver看到更详细的信息

Sql Server数据库的备份和恢复措施
最常用的操作,新手们看看……

一、备份数据库

1
、打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server
2
SQL Server-->双击打开你的服务器-->双击打开数据库目录
3
、选择你的数据库名称(如论坛数据库Forum-->然后点上面菜单中的工具-->选择备份数据库
4
、备份选项选择完全备份,目的中的备份到如果原来有路径和名称则选中名称点删除,然后点添加,如果原来没有路径和名称则直接选择添加,接着指定路径和文件名,指定后点确定返回备份窗口,接着点确定进行备份

二、还原数据库

1
、打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server
2
SQL Server-->双击打开你的服务器-->点图标栏的新建数据库图标,新建数据库的名字自行取
3
、点击新建好的数据库名称(如论坛数据库Forum-->然后点上面菜单中的工具-->选择恢复数据库
4
、在弹出来的窗口中的还原选项中选择从设备-->点选择设备-->点添加-->然后选择你的备份文件名-->添加后点确定返回,这时候设备栏应该出现您刚才选择的数据库备份文件名,备份号默认为1(如果您对同一个文件做过多次备份,可以点击备份号旁边的查看内容,在复选框中选择最新的一次备份后点确定)-->然后点击上方常规旁边的选项按钮
5
、在出现的窗口中选择在现有数据库上强制还原,以及在恢复完成状态中选择使数据库可以继续运行但无法还原其它事务日志的选项。在窗口的中间部位的将数据库文件还原为这里要按照你SQL的安装进行设置(也可以指定自己的目录),逻辑文件名不需要改动,移至物理文件名要根据你所恢复的机器情况做改动,如您的SQL数据库装在D:"Program Files"Microsoft SQL Server"MSSQL"Data,那么就按照您恢复机器的目录进行相关改动改动,并且最后的文件名最好改成您当前的数据库名(如原来是bbs_data.mdf,现在的数据库是forum,就改成forum_data.mdf),日志和数据文件都要按照这样的方式做相关的改动(日志的文件名是*_log.ldf结尾的),这里的恢复目录您可以自由设置,前提是该目录必须存在(如您可以指定d:"sqldata"bbs_data.mdf或者d:"sqldata"bbs_log.ldf),否则恢复将报错
6
、修改完成后,点击下面的确定进行恢复,这时会出现一个进度条,提示恢复的进度,恢复完成后系统会自动提示成功,如中间提示报错,请记录下相关的错误内容并询问对SQL操作比较熟悉的人员,一般的错误无非是目录错误或者文件名重复或者文件名错误或者空间不够或者数据库正在使用中的错误,数据库正在使用的错误您可以尝试关闭所有关于SQL窗口然后重新打开进行恢复操作,如果还提示正在使用的错误可以将SQL服务停止然后重起看看,至于上述其它的错误一般都能按照错误内容做相应改动后即可恢复

三、收缩数据库

一般情况下,SQL数据库的收缩并不能很大程度上减小数据库大小,其主要作用是收缩日志大小,应当定期进行此操作以免数据库日志过大
1
、设置数据库模式为简单模式:打开SQL企业管理器,在控制台根目录中依次点开Microsoft SQL Server-->SQL Server-->双击打开你的服务器-->双击打开数据库目录-->选择你的数据库名称(如论坛数据库Forum-->然后点击右键选择属性-->选择选项-->在故障还原的模式中选择简单,然后按确定保存
2
、在当前数据库上点右键,看所有任务中的收缩数据库,一般里面的默认设置不用调整,直接点确定
3
、收缩数据库完成后,建议将您的数据库属性重新设置为标准模式,操作方法同第一点,因为日志在一些异常情况下往往是恢复数据库的重要依据


四、设定每日自动备份数据库

强烈建议有条件的用户进行此操作!
1
、打开企业管理器,在控制台根目录中依次点开Microsoft SQL Server-->SQL Server-->双击打开你的服务器
2
、然后点上面菜单中的工具-->选择数据库维护计划器
3
、下一步选择要进行自动备份的数据-->下一步更新数据优化信息,这里一般不用做选择-->下一步检查数据完整性,也一般不选择
4
、下一步指定数据库维护计划,默认的是1周备份一次,点击更改选择每天备份后点确定
5
、下一步指定备份的磁盘目录,选择指定目录,如您可以在D盘新建一个目录如:d:"databak,然后在这里选择使用此目录,如果您的数据库比较多最好选择为每个数据库建立子目录,然后选择删除早于多少天前的备份,一般设定47天,这看您的具体备份要求,备份文件扩展名一般都是bak就用默认的
6
、下一步指定事务日志备份计划,看您的需要做选择-->下一步要生成的报表,一般不做选择-->下一步维护计划历史记录,最好用默认的选项-->下一步完成
7
、完成后系统很可能会提示Sql Server Agent服务未启动,先点确定完成计划设定,然后找到桌面最右边状态栏中的SQL绿色图标,双击点开,在服务中选择Sql Server Agent,然后点击运行箭头,选上下方的当启动OS时自动启动服务
8
、这个时候数据库计划已经成功的运行了,他将按照您上面的设置进行自动备份

修改计划:
1
、打开企业管理器,在控制台根目录中依次点开Microsoft SQL Server-->SQL Server-->双击打开你的服务器-->管理-->数据库维护计划-->打开后可看到你设定的计划,可以进行修改或者删除操作

五、数据的转移(新建数据库或转移服务器)

一般情况下,最好使用备份和还原操作来进行转移数据,在特殊情况下,可以用导入导出的方式进行转移,这里介绍的就是导入导出方式,导入导出方式转移数据一个作用就是可以在收缩数据库无效的情况下用来减小(收缩)数据库的大小,本操作默认为您对SQL的操作有一定的了解,如果对其中的部分操作不理解,可以咨询动网相关人员或者查询网上资料
1
、将原数据库的所有表、存储过程导出成一个SQL文件,导出的时候注意在选项中选择编写索引脚本和编写主键、外键、默认值和检查约束脚本选项
2
、新建数据库,对新建数据库执行第一步中所建立的SQL文件
3
、用SQL的导入导出方式,对新数据库导入原数据库中的所有表内容

利用数据库日志恢复数据到时间点的操作
由于不正常的数据丢失,而又不想使用备份数据还原,只要原来有备份且当前日志保存完好,可以采用这个方法试试,说不定可挽回损失……

1,如果误操作之前存在一个全库备份(或已有多个差异备份或增量备份),首先要做的事就是进
进行一次日志备份(如果为了不让日志文件变大而置trunc. log on chkpt.选项为1那你就死翘了)
    backup log dbName to disk='fileName'
2
,恢复一个全库备份,注意需要使用with norecovery,如果还有其他差异或增量备份,则逐个恢

    restore database dbName from disk='fileName' with norecovery
3
,恢复最后一个日志备份即刚做的日志备份,指定恢复时间点到误操作之前的时刻
    restore log dbName from disk='fileName'
    with stopat='date_time'

以上这些操作都可以在SQL SERVER企业管理器里完成,难度不大。。。

当然,如果误操作是一些不记日志的操作比如truncate tableselect into等操作,那么是无法利
用上述方法来恢复数据的...

SQL Server2000数据库文件损坏时如何恢复
出现这样的问题是比较严重的了,能否修复只能看你的运气……

SQL Server2000中,如果数据库文件(非系统数据库文件)遇到错误的时候,仅适用于非master,msdb的数据库。

说明如下:

1 建一个测试数据库test(数据库类型为完全)
2
建一个表,插入点记录
  create table a(c1 varchar(2))
  go
  insert into a values('aa')
  go
  insert into a values('bb')
  go
3
作完全备份,到文件test_1.bak
4
在作一点修改
  insert into a values('cc')
  go
  create table b(c1 int)
  go
  insert into b values(1)
  go
  insert into b values(2)
  go


5 shutdown 数据库服务器
6
ultraedit编辑数据库文件test_data.mdf,随便修改点字节内容,相当于数据库遭到致命的损坏。
7
启动数据库,并且运行企业管理器,点开数据库,看到test变成灰色,而且显示置疑。
8
运行isql -SLocalhost -Usa -P
1> backup log test TO DISK='D rogram FilesMicrosoft SQL ServerMSSQLBACKUP
est_2.bak' WITH NO_TRUNCATE
2>go
已处理 2 页,这些页属于数据库 'test' 的文件 'TEST_Log'(位于文件 1 上)。
BACKUP LOG
操作成功地处理了 2 页,花费了 0.111 秒(0.087 MB/秒)。

9 进行恢复最老的完全备份
1> RESTORE DATABASE test FROM DISK='D rogram FilesMicrosoft SQL ServerMSSQL
BACKUP est_1.bak' WITH NORECOVERY
2> go
已处理 96 页,这些页属于数据库 'test' 的文件 'TEST_Data'(位于文件 1 上)。
已处理 1 页,这些页属于数据库 'test' 的文件 'TEST_Log'(位于文件 1 上)。
RESTORE DATABASE
操作成功地处理了 97 页,花费了 0.107 秒(7.368 MB/秒)。

10 恢复最近的日志
1> RESTORE LOG test FROM DISK='D rogram FilesMicrosoft SQL ServerMSSQLBACKU
P est_2.bak' WITH RECOVERY
2> go
已处理 2 页,这些页属于数据库 'test' 的文件 'TEST_Log'(位于文件 1 上)。
RESTORE LOG
操作成功地处理了 2 页,花费了 0.056 秒(0.173 MB/秒)。

存储过程编写经验和优化措施
经验之谈,看看……

一、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。 

  二、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写又没有一定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。 

  三、内容: 

  1、开发人员如果用到其他库的TableView,务必在当前库中建立View来实现跨库操作,最好不要直接使用“databse.dbo.table_name”,因为sp_depends不能显示出该SP所使用的跨库tableview,不方便校验。  

  2、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,做过自身的查询优化检查。 

  3、高程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点:  

  a)SQL的使用规范:

   i. 尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。

   ii. 尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。

   iii. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作。

   iv. 注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。

   v. 不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

   vi. 尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)count(*)更有效率。

   vii. 尽量使用“>=”,不要使用“>”

   viii. 注意一些or子句和union子句之间的替换

   ix. 注意表之间连接的数据类型,避免不同类型数据之间的连接。

   x. 注意存储过程中参数和数据类型的关系。

   xi. 注意insertupdate操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。

b)索引的使用规范:

   i. 索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。

   ii. 尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引

   iii. 避免对大表查询时进行table scan,必要时考虑新建索引。

   iv. 在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。

   v. 要注意索引的维护,周期性重建索引,重新编译存储过程。  

  c)tempdb的使用规范:

   i. 尽量避免使用distinctorder bygroup byhavingjoincumpute,因为这些语句会加重tempdb的负担。

   ii. 避免频繁创建和删除临时表,减少系统表资源的消耗。

   iii. 在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;如果数据量不大,为了缓和系统表的资源,建议先create table,然后insert

   iv. 如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用到该临时表的索引。

    v. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定。

    vi. 慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用tempdb的系统表。  

d)合理的算法使用:  

  根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令:set statistics io on, set statistics time on , set showplan on


sql server 2000安装问题集

一、xp下面装sql server 2000
SQL Server 2000 Driver for JDBC: Error establishing socket


以下的方法你每种的去试试:
#
检查一下sql serverconnection有没有full.

#
如果是认证的问题.

可到sql enterprice manager->指定server->内容->安全性.

把验证改为 SQL server windows.

#
点选属性检查一下port是否正确.

#
执行%MSSQL_HOME%"80"Tools"Binn"SVRNETCN.exe

TCP/IP启用.

#
关掉防火墙.

#
SQL server updatesp3:
http://www.microsoft.com/sql/downloads/2000/sp3.asp

#reinstall

可能是端口的问题,看一看端口吧:

c:"windows"system32"netstat -an


我期待的0.0.0.0:1433 没有出现


查看事件查看器才发现,原来SQL在和1433端口绑定时失败.用我自己的查询分析器链自己的SQL是没有问题的,可是别人链我的机器就不行了(自己的机器链接时和从网络上链接时,是不太一样的)


怎么办?


重启一下机器再说吧,端口起不来再找原因.


重启机器,OK!


安装SQL server 选择开始安装,


接下去就看不见安装对话框了

二、再次双击SETUP 结果系统出现另一个安装程序事例正在运行还是安装不了,等了好久,安装程序在任务管理器中显示没有响应”,过会就消失了,不过进程还在列表中。
1
bbs上有人说先装msde 再装就可以,trying-->失败,连MSDE也装不上了1530
2
google搜索,一次特殊的SQL Server安装奇遇里说安全模式下可以安装,我也到安全模式下去了。

三、错误提示:以前的某个程序安装已在安装计算机上创建挂起的文件操作。运行安装程序之前必须重新启动计算机

G
一下,SQL Server 安装:以前的某个程序安装已在安装计算机上创建挂起的文件操作,

打开注册表编辑器,在HKEY_LOCAL_MACHINE"SYSTEM"CurrentControlSet"Control"Session Manager中找到PendingFileRenameOperations项目,并删除它。这样就可以清除安装暂挂项目。

注册表那个键值删了,果然可以了。


四、安装到最后,显示正在启动服务器和安装您选择的配置,就没动静了,等好久。我重启了,Once more 还是一样。
  1
打开注册表

"开始"--"运行"键入 "regedit"
2
按下列顺序点击打开
 + HKEY_LOCAL_MACHINE
 + SOFTWART
 + Microsoft
 + Windows
 + CurrentVersion
 + Setup
 + ExceptionComponents
3
ExceptionComponents 下面的包含SQL的文件夹全部删除!

选择左边的文件夹,观察其FriendlyName键值,如果有SQL字样,把选择个的该文件夹删除即可,我的是三个,可能和你的有所区别
4
重新启动:
5
重新运行 SQL Server 2000的安装,选修改实例。这时可以安装结束
6
。再重新运行 SQL Server 2000的安装,选高级,修复注册表。

1.      
sql server 2000 以前的某个程序安装已在安装计算机上创建挂起的文件操作解决办法

2.       新装或者以前装过sql server,后来删掉。现在重装,却出现以前的某个程序安装已在安装计算机上创建挂起的文件操作。运行安装程序之前必须重新启动计算机错误。无法进行下去。 

参考网上资料,总算搞定。步骤是: 

1
)添加/删除程序中彻底删除sql server 

2
)将没有删除的sql server目录也删除掉。 

3
)打开注册表编辑器,在HKEY_LOCAL_MACHINE"SYSTEM"CurrentControlSet"Control"Session Manager中找到PendingFileRenameOperations项目,并删除它。这样就可以清除安装暂挂项目。 

4
)删除注册表中跟sql server相关的键。

其实估计只要做第3步就可以搞定,这样就可以清除安装暂挂项目。自己是先走了124,最后做了3才搞定。所以估计3才是最关键的。

如果上面还是不能得到解决

那么再试下下面的:

将以下两个从注册表中删除,一定可以解决SQL挂起问题: 
一、开始"运行"输入regedit回车 
+HKEY_LOCAL_MACHINE 
+SYSTEM 
+CurrentControlSet 
+Control 
+Session Manager
下的FileRenameOperations删掉 
二、+HKEY_LOCAL_MACHINE 
+SOFTWARE 
+Microsoft 
+Windows 
+CurrentVersion 
+Setup 
+ExceptionComponents
下的东西全部删掉如: 
{077ACEC7-979C-40AB-9835-435BA1511E0D} 
{30C7234B-6482-4A55-A11D-ECD9030313F2} 
{3FDF25EE-E592-4495-8391-6E9C504DAC2B} 
{60204BB3-7078-4F70-8F69-68297621941C}...... 
总之有几项,就删几项,删掉后重启,再装SQL Server,就不会提示有挂起了。

在注册表中和系统中删除mssql相关的东西就OK

1. ASPAccess数据库连接:
%
dim conn,mdbfile
mdbfile=server.mappath("
数据库名称.mdb")
set conn=server.createobject("adodb.connection")
conn.open "driver={microsoft access driver
(*.mdb)};uid=admin;pwd=
数据库密码;dbq="&mdbfile
%>
2. ASP
SQL数据库连接:
%
dim conn
set conn=server.createobject("ADODB.connection")
con.open "PROVIDER=SQLOLEDB;DATA
SOURCE=SQL
服务器名称或IP地址;UID=sa WD=数据库密码;DATABASE=数据库名称
%>

建立记录集对象:

set rs=server.createobject("adodb.recordset")
rs.open SQL
语句,conn,3,2

3. SQL常用命令使用方法:
(1)
数据记录筛选:
sql="select * from
数据表 where 字段名=字段值 order by 字段名 [desc]"
sql="select * from
数据表 where 字段名 like '%字段值%' order by 字段名 [desc]"
sql="select top 10 * from
数据表 where 字段名 order by 字段名 [desc]"
sql="select * from
数据表 where 字段名 in ('1','2','3')"
sql="select * from
数据表 where 字段名 between 1 and 2"

(2) 更新数据记录:
sql="update
数据表 set 字段名=字段值 where 条件表达式"
sql="update
数据表 set 字段1=1,字段2=2 …… 字段n=n where 条件表达式"

(3) 删除数据记录:
sql="delete from
数据表 where 条件表达式"
sql="delete from
数据表" (将数据表所有记录删除)

(4) 添加数据记录:
sql="insert into
数据表 (字段1,字段2,字段3 …) values (1,2,3 …)"
sql="insert into
目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表)

(5) 数据记录统计函数:
AVG(
字段名) 得出一个表格栏平均值
COUNT(*|
字段名) 对数据行数的统计或对某一栏有值的数据行数统计
MAX(
字段名) 取得一个表格栏最大的值
MIN(
字段名) 取得一个表格栏最小的值
SUM(
字段名) 把数据栏的值相加
引用以上函数的方法:
sql="select sum(
字段名) as 别名 from 数据表 where 条件表达式"
set rs=conn.excute(sql)
rs("别名") 获取统的计值,其它函数运用同上。

(5) 数据表的建立和删除:
CREATE TABLE
数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… )

讲一下这个2000的一些privilege

Privilege,为本地管理员提供了一种手段,可以控制允许什么人具有什么权限或者能执行什么样的系统操作,

如允许交互式登陆等等。这里我们说的特权是指特殊操作所需的权限,如备份呀什么的!一旦授予了某种特权,

这些特权就会包括在用户的安全访问令牌中。这是一些基本的概念,可以看以下,比较容易明白。

系统为了管理的方便总是为每个本地组分配了相应的特权,而且从来不改变这个特权,这些东东在NT系统上可以分为内置能力,标准用户权力,高级用户权力这么几种,但是在2000中标准权利和高级权力已经被用户特权所取代,只有在为委派而信任计算机和用户帐户(SeEnableDelegationPrivilege)和把计算机从dock中移出(SeUndockPrivilege)这两种情况下可以把NT的权利映射到2000中的特权。
注意一下2000的一些问题。并非所有能力都有匹配的权利,因此,不可能用权力完全匹配组的内置能力。而由于

特定组能力的预定义分配和不能把所有能力复制为权力,就难以区分任务,并且只能强制使用最低特权的概念。

那么在域一级下就缺少一个安全结构,导致了难以授予管理的功能。2000AD引入后,就允许区分任务,也可授

domainOU相应的管理层次。

下面来谈一下具体的一些用户特权,应当有26个,也有说28个的。

SeTcbPrivilege
成为OS的一部分
允许进程可以像用户一样被鉴别,因此可以像用户一样访问相应的资源。只有底层的鉴别服务需要这样的特权所以无论是工作站,独立服务器,还是DC都没有把这个设为某人权利。

SeMachineAccountPrivilege
添加工作站到域为了这个特权可以启用,必须保证这个用户在域控制器本地安全策略中的才行。

SeBackupPrivilege
备份文件和目录。
允许用户绕过文件和目录的权限来做备份。只有当应用程序尝试访问NTFS备份API时才检查这个特权。默认情况下,这个特权分配给AdministratorsBackup Operators

SeChangeNotifyPrivilege
回避遍历检查。
允许用户来回移动目录,但是不能列出文件夹的内容。默认情况下,这种特权被赋予Administrators,

Backup Operators, Power Users, Users ,and Everyone,换句话说就是所有人都有这种权利。

SeSystemTimePrivilege
改变系统时间。
默认情况下AdministratorsPower Users有这种权利。

SeCreatePagefilePrivilege
创建分页文件。
允许用户创建和改变一个分页文件的大小。默认情况下,只有Administrators有这个特权。

SeCreateTokenPrivilege
创建令牌对象。
允许进程调用NtCreateToken()或者是其他的Token-Creating APIs创建一个访问令牌。

SeCreatePermanentPrivilege
创建永久共享对象。
允许进程在2000项目管理器中创建一个目录对象。

SeDebugPrivilege
调试程序。
允许用户连接一个Debugger来调试任何进程。默认情况下Administrators有该特权。

SeEnableDelegationPrivilege
为委派而信任计算机和用户帐户

允许用户为了委派而改变信任,只有当用户或者是计算机对该对象的帐户控制标志有写权限的时候可以。

SeRemoteShutdownPrivilege
远程关闭系统。
Administrators
在默认情况下有此特权。

SeAuditPrivilege
产生安全审核。
允许一个应用程序在安全日志中,创建,产生,增加一条记录。

SeIncreaseQuotaPrivilege
增加限额。
允许一个有写属性的进程利用其他进程从而取得更多的处理器限额,这种特权有利于系统调试,但是也有导致
DOS
的可能。

SeIncreaseBaseProrityPrivilege
增加调度优先级。
允许一个有写属性的进程利用其它进程来获得更多的执行优先权。有这种特权的用户可以在Task管理器中改变一个进程的调度优先权。默认情况Administrators有该特权。

SeLoadDriverPrivilege
安装和卸载设备驱动程序。
允许用户安装和卸载即插即用设备的驱动程序,不是即插即用的不受这个特权影响,但是只能被
Administrators
所安装。因为驱动程序是作为被信任的程序来运行的,这需要很高的特权。而这种特权可能会被用于安装恶意程序,和破坏性的访问。默认情况下Administrators有该特权。

SeSecurityPrivilege
管理审计和安全日志。
允许用户指定对象访问的审计。有这种特权的用户也可以清空安全日志。默认情况下Administrators有该特权

SeSystemEnvironmentPrivilege
修改firmware环境变量。
允许用户使用进程通过一个API来设置系统环境变量,另外,也可以让用户使用System Properties来做到以上这一步。默认情况下Administrators有该特权。

SeProfileSingleProcessPrivilege
Profile
单一进程。
允许用户使用性能监视器来监视nonsystem进程。默认情况下Administrators有此特权。

SeSystemProfilePrivilege
Profile
系统性能。
允许用户使用性能监视器来监视system进程。默认情况下Administrators有此特权。

SeUndockPrivilege
将计算机中dock中删除。
允许用户使用Eject PC从坞中将计算机移出,默认情况下Administrators, Power Users, Users均有此特
权。

SeAssignPrimaryTokenPrivilege
替换一个进程级令牌。
允许一个父进程替换相关的子进程的访问令牌。

SeRestorePrivilege
恢复文件和目录。
允许用户绕过文件及目录权限来恢复备份文件。默认情况下AdministratorsBackup Operators有此特权。

SeShutdownPrivilege
关闭系统。
允许用户关闭本地计算机。默认情况下Administrators, Backup Operators, Power Users, Users都有该特权,但是在2000 ServerUsers没有此特权。

SeSynchAgentPrivilege
同步目录服务数据。
允许一个进程提供目录同步服务,这个特权只有在DC上。默认情况下域的AdministratorsLocalSystem帐户有此特权。

SeTakeOwnershipPrivilege
取得文件所有者身份。
允许用户取得在系统中任何可得到的对象的所有者身份,包括:AD对象,文件,文件夹,打印机,注册表键,进程和线程。默认情况下Administrator有此特权

dim conn
dim connstr
dim connType,dbPath

connType=1
Set conn= Server.CreateObject("ADODB.Connection")

IF conn.State = 0 Then
 IF connType= 1 Then
  connstr = "Provider=SQLOLEDB;uid=shadow;pwd=XXXXXX;Initial Catalog=XXXXXX;server=(local);"
 Else
  dbPath = Server.Mappath(""") & ""hkcn"database"webhkcn.mdb"
  connstr = "Provider=Microsoft.JET.OLEDB.4.0;Data Source="& dbPath &";"
 End If
 conn.Open connstr
End If

Function SQLExecute(SqlStr)
 on error resume next
 Dim Rs
 Set Rs=Server.CreateObject("Adodb.Recordset")
 Rs.open SqlStr,conn,1,3
 Set SQLExecute=Rs
 If Err.Number <> 0 Then
  Response.Write("<font color=red>
抱歉你在访问本页时出现一个错误以下是错误的详细信息。<br>")
  Response.Write("
错误号:"&CStr(Hex(Err.Number))&"<br>")
  Response.Write("
错误对象:"&Err.Source&"<br>")
  Response.Write("
有关错误的详细描述:"&Err.Description&"<br>")
  Response.Write("
如果你始终无法访问本页请联系管理员。")
 End If
End Function
'=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
%>

<%
'=================================================
'  ublic Function
'  rogrammer by Jiang Jian(Shadow)
' Email:vbcc@sohu.com
' Date: 2003-05-26
'=================================================

Function ChkLogin(UserName,Pass)
 Dim Sql,Rs
 Sql="Select id,username,password FROM member WHERE username='"&UserName&"' And password='"& ass&"'"
 Set Rs=SQLExecute(Sql)
 If Not (Rs.bof or Rs.eof) Then
  ChkLogin=Rs("ID")
 Else
  ChkLogin=False
 End If
 Rs.Close
 Set Rs=Nothing
End Function

'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
'
判断是否非法提交数据 True 为正常 False 为非法提交
'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function ChkPost()
 Dim server_v1,server_v2
 Chkpost=False
 server_v1=Cstr(Request.ServerVariables("HTTP_REFERER"))
 server_v2=Cstr(Request.ServerVariables("SERVER_NAME"))
 If Mid(server_v1,8,Len(server_v2))<>server_v2 Then
  Chkpost=False
 Else
  Chkpost=True
 End if
End function

'====================================================
'
判断用户名是否包含非法字符 True 合法的字符串
'====================================================
Function CheckString(Str1)
 Dim N
 Dim S
 For N = 1 To Len(Str1)
  S = Asc(Mid(Str1, N))
  If S > 47 And S < 58 Or S > 64 And S < 91 Or S > 96 And S < 122 Or S = 95 Then '
合法的字符串
   CheckString=True
  Else 
   CheckString=False
  End If
 Next
End Function

判断字符是否为中文 True 合法 False 非法
'====================================================
Function IsChinese(Str)
 Dim N
 Dim S
 For N = 1 To Len(Str)
  S = Asc(Mid(Str, N))
  If S => 0  Then   
   IsChinese=False
   Exit for
  Else
   IsChinese=True
  End If
 Next
End Function

'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
'
判断是否为合法的电话号码 True 合法 False 非法
'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function IsPhone(Str)
 Dim strArray
 IsPhone=False
 strArray=Split(Str,"-",-1,1)
 IF Ubound(strArray)> 0 Then
  IF Len(strArray(0))>2 And Len(strArray(0))< 5 Then
   IF Len(strArray(1))>6 And Len(strArray(1))< 9 Then
    If IsNumeric(strArray(0))=True And  IsNumeric(strArray(1)) Then
     IsPhone=True
    End If
   End If
  End If
 End IF
End Function

'判断是否为合法的电子邮件地址 True 合法 False 非法
'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function IsValidEmail(Email)
 Dim Names, name, i, c
 IsValidEmail = True
 Names = Split(Email, "@")
 
 If UBound(Names) <> 1 Then
  IsValidEmail = False
  Exit function
 End If
  
 For Each Name IN Names
  If Len(name) <= 0 Then
   IsValidEmail = False
   Exit Function
  End If
  For i = 1 To Len(name)
   c = Lcase(Mid(name, i, 1))
   If InStr("abcdefghijklmnopqrstuvwxyz_-.", c) <= 0 And Not IsNumeric(c) Then
    IsValidEmail = False
    Exit Function
   End If
  Next
  If Left(name, 1) = "." or Right(name, 1) = "." Then
   IsValidEmail = False
   Exit Function
   End If
  Next
  
 If InStr(names(1), ".") <= 0 Then
  IsValidEmail = False
  Exit Function
 End If
 
 i = Len(names(1)) - InStrRev(names(1), ".")
 If i <> 2 And i <> 3 Then
  IsValidEmail = False
  Exit Function
 End If
 
 If InStr(Email, "..") > 0 Then
  IsValidEmail = False
 End If
End function

数据分页显示 strUrl 设置成自己本页
'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Function PageSplit(objRs,strUrl,cssClass,listSize,cssSep)
 Dim pgnum,page
 page=Request("page")
 objRs.PageSize = listSize
 pgnum=objRs.Pagecount
 if page="" or clng(page)<1 then page=1
 if clng(page) > pgnum then page=pgnum
 if pgnum>0 then objRs.AbsolutePage=page
 If page=1 Then
  Response.Write "
| 上一页 | "
 Else
  Response.Write " <a class="& cssClass &" href="&strUrl&"page=1>
</a><span class="& cssSep &"> | </span>"
  Response.Write "<a class="& cssClass &" href="&strUrl&"page="&page-1&">
上一页</a><span class="& cssSep &"> | </span>"
 End if
 If objRs.pagecount-page<1 Then
  Response.Write "
下一页 | "
 Else
  Response.Write "<a class="& cssClass &" href="&strUrl&"page="&page+1&">
下一页</a><span class="& cssSep &"> | </span>"
  Response.Write "<a class="& cssClass &" href="&strUrl&"page="&objRs.pagecount&">
</a>"
 End if
 Response.Write "
              第 "&page&" / "&pgnum&" "
End Function

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Public Function SplitPage(strContents)
 Dim Page,PageArray
  ageArray=SepPosition(strContents)
  age=Request("page")
 pgnum=UBound(PageArray)
 IF page="" or clng(page)<0 Then page=0
 IF Clng(page) > pgnum Then page=pgnum
 
 IF pgnum = 0 Then '
只有一页
  SplitPage=strContents
  Exit Function
 End IF
 
 If Page = 0 Then
  SplitPage=Mid(strContents,1,PageArray(page)-1)
 ElseIf Clng(Page)=pgnum Then
  SplitPage=Mid(strContents,PageArray(page-1)+19,Len(strContents))
 Else
  SplitPage=Mid(strContents,PageArray(page-1)+19,PageArray(page)-(PageArray(page-1)+19))
 End if
End Function

Public Function NavPage(strPage)
  age=Request("page")
 IF page="" or clng(page)<0 Then page=0
 IF pgnum > 0 Then
  IF Page = 0 Then
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page & """>
上一页</a> "
  Else
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page - 1 & """>
上一页</a> "
  End if
  
  If pgnum-Clng(Page)<1  Then
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page &""">
下一页</a> "
  Else
   Response.Write "<a class=""SepPage"" href="""&strPage&"&page=" & page + 1 & """>
下一页</a>"
  End If
  Response.Write "<span class=""I"">
" & pgnum + 1 & " 当前第 " & page + 1 & " </span>"
 End IF
End Function

Public Function SepPosition(strContents)
 Dim intPos,strPos
 Dim intPageArray,strTemp
 strTemp = "[PAGE]------[/PAGE]"
 intPos=Instr(strContents,strTemp)
  strPos = intPos
 Do While (intPos)
  intPos=Instr(intPos+19,strContents,strTemp) 
  strPos=strPos & "," & intPos
 Loop
 SepPosition=Split(strPos,",")
End Function

'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
'
截取一定数量的文字输出
'>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Public Function OutText(strText,intOutSize)
 IF Len(strText)>intOutSize Then
  OutText = Left(strText,intOutSize-3) & "..."
 Else
  OutText = strText
 End If
End Function
%>

游标使用方法:
use db1
declare my_cursor cursor scroll dynamic /*scroll
表示可随意移动游标指针(否则只能向前),dynamic表示可以读写游标(否则游标只读)*/
for
select
姓名 from 个人资料

open my_cursor
declare @name sysname
fetch next from my_cursor into @name
while(@@fetch_status=0)
begin
print @#
姓名: @# + @name
fetch next from my_cursor into @name
end
fetch first from my_cursor into @name
print @name
/* update
个人资料 set 姓名=@#zzg@# where current of my_cursor */
/* delete from
个人资料 where current of my_cursor */
close my_cursor
deallocate my_cursor


数据查询

且不说你是否正在从事编程方面的工作或者不打算学习SQL,可事实上几乎每一位开发者最终都会遭遇它。你多半还用不着负责创建和维持某个数据库,但你怎么着也该知道以下的一些有关的SQL知识。 
    
我为那些感兴趣的开发者或者能从数据库操作中得益的读者撰写了这篇关于基本SQL语法的概述性文章。本文主要讨论基本的数据操作查询,后续的文章还会继续讨论如何修改数据库自身以及更高级的查询概念。

SQL
数据库是怎么回事?
  
SQL
(结构化查询语言)就是负责与ANSI维护的数据库交互的标准。最新的版本是SQL-99,还有一个新标准SQL-200n尚处于制定过程中。大多数的数据库都至少遵守ANSI-92标准的部分子集。不过,目前对最新标准的有效性还存在一些争论。专有数据库制造商根据这些标准开发自己的产品,同时制定出自己特有的数据库存储操作新概念。几乎各种不同的数据库都包含了自己特有的语法集合,只是通常很类似ANSI标准。在大多数情况下,尽管有一些数据库实例基于特定的扩展语法会因数据库的不同而产生不同的结果,但总的说来,这些新加的语法不过是对原有标准的扩充。如果数据库操作并没有得到你希望的结果,那么你不妨事先读一读数据库制造商提供的产品说明。

假如到目前为止你头回遭遇SQL语言,那么你怎么也得先理解一些基本的SQL概念。我尽量把这些基本知识阐述得简明扼要,如果你对那些数据库术语还能忍受,你尽可跳到下一节,此外你还可以把自己的问题提交给以下的讨论区。

笼统地说,“SQL数据库其实就是关系型数据库管理系统(RDMS)通俗的叫法。对某些系统来说,数据库也指一组数据表、数据以及相互区分但结构类似的配置信息。在这种情况下,每一SQL数据库的安装都可能由若干数据库组成。在有些系统上,这种数据库则指的是表空间。

数据表是一种包含多行数据的数据库构造,这种数据库构造由命名的列组成。通常数据表构造为包含关系信息,同一数据库或表空间以内可以创建若干数据表。

表内的列保存某一种类型的数据而且应根据其保存数据的内容得以命名。例如,被称为“LastName”的列就应该在每一行包含姓氏条目。正是这一前提的存在才能让关系数据库查询返回一致的结果。字段(field)指的是某一行某一列对应的数据(或保存数据的地方)。另外,数据集合(data set)则指的是多行多列的数据,而且数据集合通常说明你的数据库或数据表内的全部数据。结果集合(result set)就是从数据库查询返回的数据;它能够描述从单一字段到数据库内全部数据这一范围内的全部信息。

数据库查询就是发送给数据库的SQL指令,这些指令向数据库请求某种施加在数据集合或数据库上的功能。

现在我们就来看看基本的数据库查询,这些查询主要涉及到对数据库内数据的操作。在本文中,所有的例子都采用了标准SQL语言,而且这些基本功能可以转换为应用在几乎各种环境下。

数据查询类型

SQL
语言中的数据查询分为4种基本类型:

SELECT
:这条语句要求数据库返回指定结果的数据集合;你可以用这一语句检索数据库中保存的信息。 
INSERT
:这条语句用来给数据表增加新一行数据。 
DELETE
:该语句从你的数据库中删除若干行数据。 
UPDATE
:该语句修改数据库内的现有数据。 
以上的这些语句都有各种各样的限定词和函数供你用来定义有关的数据集合,同时控制查询返回的结果集合。SELECT语句的选项最多。有许多种组合SELECT的查询选项,例如JOINUNION等。不过就我们目前来说,本文主要还是关注基本用途。

SELECT语句检索保存的信息
为了获得数据库中保存的信息就必须采用SELECT语句。其基本功能限制在针对单一数据表操作,当然,其他范围的构造也是有的。为了返回特定列所对应的所有数据行,你可以使用以下语句:

SELECT column1, column2 FROM table_name;

另外,使用通配符“*”可以从表中选出所有的列:

SELECT * FROM table_name;

你要愿意自己编码分析以上返回的结果当然也没问题,不过你完全可以采用方便的WHERE子句限制返回的结果集合,该子句可以让你为选择数据定义某些条件。以下查询就会返回“column1”数值等于3的所以数据行:
SELECT * FROM table_name WHERE column1 = 3;

除了“=”(等于)条件之外你还可以用到下列条件运算符:

A

等于
 
<> 
不等于
 
大于
 
小于
 
>= 
大于或等于
 
<= 
小于或等于
 

SQL 
条件语句

另外,你还可以联合WHERE语句使用BETWEENLIKE等比较运算符以及ANDOR这类逻辑运算符。注意,OR语句是包含性的的。以下有一个例子组合了以上这些概念:

SELECT * FROM table_name WHERE ((Age < 18) AND (LastName BETWEEN ‘Anderson’ AND ‘Miller’)) OR Company LIKE ‘%School%’;

用自然语言来说,这条选择语句的含义是这样的:从数据表中选出年龄小于18岁而且姓氏在“Anderson”“MIller”之间的或者其公司名称类中有“School”字样的数据行。

INSERT语句加入新数据
使用INSERT语句可以创建新的数据行。如果你希望在某一行的某个字段中赋值则要用到UPDATE语句。

插入语句的语法如下:
INSERT INTO table_name (column1, column2, column3)
VALUES (‘data1’, ‘data2’, ‘data3’);

如果你想按照表内现有列的同一顺序插入所有的值,那么你不必指定列名,当然,从可读性考虑最好不要这样做。另外,如果你列出列名则不必要按照它们在数据库中出现的顺序包括它们,只要你列出的值与它们一一对应即可。有些列你并没有为其输入新的信息所以你自然没有必要列出它们来。

一旦数据库中有了数据要修改起来也与此很相似。

UPDATE
语句和WHERE子句
UPDATE
用来修改现有的值或行里的空字段,因此它必须在匹配现有的数据集合同时提供可接受的值。除非你真地想要修改所有数据行上的值,否则你必须使用WHERE子句。
UPDATE table_name SET column1 = ‘data1’, column2 = ‘data2’
      WHERE column3 = ‘data3’;

你可以采用WHERE子句随意匹配任何一列,正在修改的一列都可以。这样会有助于你把某一特定的值修改为另一个值:

UPDATE table_name SET FirstName = ‘Shelley’
WHERE FirstName = ‘Shelly’ AND LastName = ‘Doll’;


小心DELETE语句
DELETE
语句会从数据库的数据表中删除整行。如果你仅仅想删除单一的字段则应该使用UPDATE语句把它修改为代表应用程序中的NULL的其他空值。一定要小心使用带WHERE子句的DELETE语句,否则你可能会遭遇清空全部数据表的风险。
DELETE FROM table_name WHERE column1 = ‘data1’;

一旦你数据库中删除某一行数据就不可再后悔了,因此一般来说,最好在数据表中包括一名为“IsActive”的列或类似的指示信息,这样你就可以把该列数据设置为零表示数据禁用。只有在你确信不再需要受到影响的信息之后你才可以用DELETE语句。

小结
SQL
就是数据库的语言,我们已经了解了数据查询中所采用的最基本命令语句。但还有很多基本概念尚未涉及,例如SUNCOUNT函数等,但以上列出的这些命令应该足够你开始着手数据库操作了。
SQL,
数据库,本文章转载自 婚嫁千千缘

在这篇文章里,我们将就其他一些SQL函数和子句进行阐述,供你用于基本的SELECT数据查询中。


SELECT
选项精制结果
正如我们从上一篇文章中所读到的那样,SELECT语句具有种类繁多的各类选项,这些选项可以用来控制数据返回的方式。这些选项以子句、关键词和函数的形式存在。

子句是一种修改结果的语句。子句不是必要的语句但它对数据的内容及其显示进行了提炼。WHERE子句就是这样的子句。

关键词触发数据库的内在功能。这些关键词在有时甚至是查询所必需的。例如“INSERT INTO table_name (column1) VALUES (‘data1’);”语句中的INTOVALUE就是如此。我们将了解DISTINCT关键词,它能触发一些非常有用的可选功能。

下面总结了一些最常用的子句、关键词和函数。然后我会对每一部分举例说明。

ORDER BY – 
按照指定列排序返回结果的子句
DISTINCT – 
只返回结果集合内唯一行的关键词 
COUNT -- 
返回匹配查询的数据行总数数值的函数 
AVG – 
该函数返回指定列的平均值
SUM –
该函数把指定的列中的数字加起来
MIN – 
该函数返回列中最小的非NULL
MAX –
该函数返回列中的最大值
GROUP BY – 
按列汇集查询函数结果的子句
ORDER BY对查询结果排序
ORDER BY
子句让数据库对查询结果排序,这样你就无须自己编写应用程序进行手工排序了。ORDER BY子句必须放在查询语句的结尾。其基本用法如下:


SELECT * FROM Contacts ORDER BY first_name;

你可以随意在任何选择语句中使用ORDER BY 子句返回多列结果。你还可以用它连接其他子句:
SELECT first_name, last_name FROM Contacts WHERE first_name BETWEEN ‘a’ AND ‘k’ ORDER BY last_name;

你可以对多列数据排序。优先顺序按从左到右依次降低,所以查询语句中各列的排列顺序很重要。
SELECT * FROM Contacts ORDER BY company, last_name, first_name;

查询结果默认按数字或者字母的升序排序。你可以在ORDER BY 子句后面加上DESC关键词改成降序排列。在下面的例子中,最高的net_amount排在最先(降序)。假如两行或者两行以上数据都包含了同样的net_amount值,那么同行中last_name值在字母表中最先出现的排先,因为last_name一列还是按照升序排序的。
SELECT * FROM Sales ORDER BY net_amount DESC, last_name, first_name;

在按照定义的列名排序以后,大多数数据库随后将按照数据表内的第一列排序然后顺序向右再排序。具体的实现各有变化,因此,如果排序在应用中比较重要那么你应该明确地定义所要排序的列。

另外一值得注意的问题是,采用ORDER BY子句(以及WHERE子句),你正在用来排序结果的数据列并不一定得是返回结果集合的一部分。只要所有引用的列都在数据表内存在则下例完全有效:

SELECT company, first_name, net_amount FROM Sales ORDER BY start_date, last_name;

DISTINCT
返回不重复结

DISTINCT关键词只返回结果集合内不重复的数据行。例如,有时你可能需要找出Sales表内的公司,但是你又不想看见每个条目。于是你可以用DISTINCT对应每一公司名返回一行数据:

SELECT DISTINCT company FROM Sales;

在使用DISTINCT时,它适用于所有的请求列。如果你打算列出表内的所有销售人员和他们所代表的公司而非每一销售记录,那么你可以使用下列语句。注意,这样操作还可能返回同一公司的若干条目等等。

SELECT DISTINCT company, last_name, first_name FROM Sales;

你还可以在对结果缩小范围和进行排序时结合SELECT语句使用DISTINCT。为了确定显示的内容,数据库首先会证实精练的请求是否匹配数据行,然后应用DISTINCT功能。在全部结果集合都得以确定之后即处理ORDER BY子句。如下例所示,只有net_amount大于100的数据行才被返回。由于DISTINCT保留遇见的第1个匹配查询条件的数据行而丢弃其他匹配行,所以ORDER BY语句所引用的net_amount看起来就好象产生了随机的结果。

SELECT DISTINCT company, last_name, first_name FROM Sales WHERE net_amount > 100 ORDER BY company, net_amount;


函数应用逻辑
返回单一值的函数称做聚集函数(aggregate function)。通过应用程序访问下列聚集函数的结果时,包含结果的字段名就是你所使用的实际函数。例如,在分析你的数据库结果时,结果数组的键值可能如下所示:

$keyname = “COUNT(*)”;
$resultkey = “AVG(net_amount)”; COUNT
COUNT
函数计算出结果集合中的数据行数。和其他函数一样它接受一个参数。以下的基本示例能告诉你数据表内的行数:SELECT COUNT(*) FROM Sales;

你也可以用它来计算任何结果集合中的行数。

SELECT COUNT(*) FROM Sales WHERE net_amount > 100;

如果你想看看某特定列有多少行包含非空值,那你不妨对该列使用COUNT函数。注意,除非数据库设置为字段为空时缺省填充NULL否则将返回表内数据行的总数。另外,列出的列在超出一个的情况下会引起错误。

SELECT COUNT(company) FROM Sales;
 
COUNT
还可以用来计算DISTINCT结果集合中的行数。
SELECT COUNT(DISTINCT company, last_name) FROM Sales;

COUNT
语句通常用在程序中确定FOR循环的循环次数。

下面的例子演示了以上各种方式。首先,包括GROUP BY子句可以令你指定要显示的其他列。然而,你得知道这个例子将返回在组中遇到的第1last_name值;Sum( net_amount )将显示全部公司的结果而不仅仅针对匹配姓氏的数据行。这是因为,我们只使用了Company字段来定义我们的组。

SELECT company, last_name, SUM(net_amount) FROM Sales GROUP BY company;

在上面的例子中,last_name列实际上并没有提供什么有用的信息,但这样做是为了在下一个例子中要用到的功能做准备。你可以创建多列定义的组。这样就可以在结果集合中产生针对特定行的函数结果,而结果集合则是由所有指定的GROUP BY列联合起来创建的:

SELECT company, AVG(net_amount), last_name FROM Sales GROUP BY company, last_name;
 

上面的例子给每家公司中每一姓氏给出了平均的net_amount。你列出GROUP BY列的顺序控制着结果的排序,但是实际的函数值结果是一样的。


下面的例子表明如何组织结果而不显示分组的列。在有些场合这样做是很有用的,例如,如果要显示个人的销售量但却不显示姓名就能用上下面的例子了:

SELECT company, COUNT(sale_id) FROM Sales GROUP BY company, last_name;

AVG
AVG
返回某列所有字段的平均值,该列必须是数字数据类型。该函数用列的名字作为其参数,如果列字段数据类型是非数字类型的则函数返回“0”SELECT AVG(net_amount) FROM Sales;

你可以结合子句限制该函数的应用范围。

SELECT AVG(net_amount) FROM Sales WHERE company LIKE ‘%ABCD Co%’;

就象所有聚集函数一样,ORDER BY语句将被忽略。

SUM

SUM
的工作方式和AVG差不多,只不过该函数返回结果集合中所有字段值的和。
SELECT SUM(net_amount) FROM Sales WHERE net_amount > 100;

AVG
SUMMINMAX函数在没有指定列的情况下都会返回错误,所以你不能使用“*”通配符。

MIN
MIN
返回指定列中最小的非空值。如果指定列是数字数据类型则结果将是最小的数字。如果它是一种字符串数据类型则函数将返回按字母表顺序出现的第1个值。SELECT MIN(net_amount) FROM Sales WHERE last_name = “Smith”;
SELECT MIN(last_name) FROM Sales;
 

MAX

MAX
的工作方式和MIN函数一样,只不过该函数返回最大的非空值。该函数也可以用于字符串或者数字列
SELECT MAX(net_amount) FROM Sales;
SELECT MAX(company) FROM Sales WHERE net_amount > 100;

MAX
函数有时还用在包含自动递增键字段的列上确定下一条目的键ID。除非你正在运行一个非公开的数据库,否则在使用这一信息插入下一条目时务必谨慎,以防其他用户先你执行数据操作。
GROUP BY 
令函数更有用

  
虽然以上提到的所有这些函数都能提供相当有用的信息,但是,如果有GROUP BY子句帮忙的话更能让你在列的字段子集中应用这些函数。不要对你的Sales表中每一家公司一次又一次地执行MAX函数查询——你完全可以带GROUP BY子句获得同样的结果:

SELECT company, MAX(net_amount) FROM Sales GROUP BY company;

这样做可以获得每家公司net_amount的的最大值。在选择多列名的时候也可以采用该语句,你还可以用多列来对函数结果分组


限制使用GROUP BY的查询
如你在以上示例中所看到的那样,你可以结合WHERE字句利用以上的概念限制查询的范围。WHERE子句会首先被计算,然后执行函数。在使用组的时候就是这样的。

SELECT company, AVG(net_amount), FROM Sales WHERE net_amount > 100 GROUP BY company;

上面的例子只对那些满足WHERE限制条件的数据行适用AVG函数。注意,WHERE子句必须放在GROUP BY子句之前。你还可以用HAVING语句对分组计算之后限制返回的结果集合。

SELECT company, AVG(net_amount), FROM Sales WHERE last_name BETWEEN ‘a’ AND ‘m’ GROUP BY company HAVING AVG(net_amount) > 500;
 

上面的语句计算每家公司net_amount的平均值,而且只计算那些姓氏满足限制条件的销售人员的销售量,同时只显示大于500的结果。

SQL功能与特性
  其实,在前面的文章中,已经提及SQL命令的一些基本功能,然而,通过SQL命令,程序设计师或数据库管理员(DBA)可以:
  (一)建立数据库的表格。(包括设置表格所可以使用之空间)
  (二)改变数据库系统环境设置。
  (三)针对某个数据库或表格,授予用户存取权限。
  (四)对数据库表格建立索引值。
  (五)修改数据库表格结构。(新建、删除或是修改表格字段)
  (六)对数据库进行数据的新建。
  (七)对数据库进行数据的删除。
  (八)对数据库进行数据的修改。
  (九)对数据库进行数据的查询。
  这几项便是通过SQL命令可以完成的事情,看起来是不是比起查询两个字所代表的功能要多的多了呢?

  SQL语法的分类

  其实SQL命令并不是非常多,可是要把SQL用到出神入化,却也只需要短短几个命令便够,因为SQL命令是针对关系型数据库所建立出来的语法叙述,所以SQL在这类数据库中所发挥的功能非常的强,以下将针对在VB中常用的SQL语法基本命令加以分类介绍。在说明SQL的命令以及使用语法之前,以下将SQL做了的分类,在致上SQL语法所使用到的类型,可以说都已包含在这些类别当中。

  第一类、属性词(Predicates

  在SQL命令中用来指明所要选择的记录的方式。如ALLTOPDISTINCT等等。

  第二类、声明(Declaration

  针对SQL ParameterParameter Query 的名称与数据类型做声明,如PARAMETERS的声明等等。

  第三类、条件子句(Clause

  在SQL的查询中,利用一些表达式定义出查询的条件,以缩小寻找的范围,如WHERE

  第四类、运算符(Operator)与操作数(Operation

  在SQL的查询中,与Operation共同组成表达式(Expression),如BETWEEN....AND 运算符与INNER JOIN操作数。

  第五类、函数(Function

  一些SQL常见的函数,像是AVG()是求算数平均数的函数。

  第六类、SQL语句(Statement

  SQL的语句,可以说是SQL语法的主体,用来对某一个特定的数据库发出指示,并返回相关的数据,而SQL的语法结构,基本上可以利用下面

  的式子来表示:命令+条件子句

  例如:

  SELECT*FROM TAB WHERE TAB.NAME='A'

  其中的“FROM....WHERE”便是一个条件子句,其实SQL的语法并不难,您只需记住这样的一个规则,相信可以很快的了解SQL用法。

  SQL语法与命令


SELECT
语句
SELECT[predicate]{*|table.*|[table.]field [,[table.]field2[,...]]} [AS alias1 [,alias2[,...]]]
FROM tableexpression [,...][IN externaldatabase]
[WHERE...]
[GROUP BY...]
[HAVING...]
[ORDER BY...]
[WITH OWNERACCESS OPTION]
SELECT
语句包括下面几个部分
predicate



如前面所述,包括了ALLDISTINCT,DISTINCTROW,TOP 我们可以利用这样的语句去限制查询后所得的结果。

  *

  从指定表格中指定所有的字段。

  table

  针对被选择出的记录的字段,所指定表格的名称。

  field1,field2

  想要读取数据的字段名称,如果包含了一个以上的字段,会依照列出的顺序来读取数据。

  alias1,alias2

  用来替代在表格实际字段名称的化名。

  tableexpression

  表格名称或包含我们所想要的数据的表格。

  externaldatabase

  若使用到不是目前的数据库则将其名字定义在externaldatabase当中。
 
  ALL,DISTINCT,DISTINCTROW,TOP属性词用法

  SELECT [ALL|DISTINCT|DISTINCTROW|[TOP n[PERCENT]]] FROM table

  ALL

  若是您不指定任何的字段数据,则Microsoft Jet数据库引擎(database engine)将会选择所有的字段,并依据所定的条件查询出需求数据集。
空间,SQL,数据库,本文章转载自 婚嫁千千缘

例如下面这两个例子将会具有相同的效果,都会从职员表格中返回所有字段的数据。

  例如:

  若是我们要查询出职员表格中的所有记录,可以通过下面的语句来完成。


SELECT ALL* FROM
职员表格; DISTINCT



  
  对某个表格所选择的字段数据,略过重复的情况,也就是说,针对某个字段查询出来的记录结果是唯一的。例如有许多存放在职员表格的职员

  数据,也许会具有相同的姓名,所以若是我们用SQL语句中的SELECT DISTINCT,则查询出来的结果将会针对不一样的姓名加以筛选。若是您把

  DISTINCT 加以省略,则这样的查询会显示所有的记录。

  DISTINCTROW

  将整条记录重复的记录忽略掉,而不是只有针对某一个字段的数据。

  table

  指定查询记录所需要的表格。

  例如:


  SELECT DISTINCTROW 公司名称


  FROM 顾客表格 INNER JOIN 订单表格

  ON 顾客表格.顾客ID=订单表格.顾客ID


  ORDER BY 公司名称;


  如果您忽略 DISTINCTROW 则会对每个公司产生一行以下的订单数据。此外,若是DISTINCTROW只有用在一个表格当中,则会被省略掉。

  TOP

  从第一条或最后一条开始(利用ORDER BY条件子句),返回特定条数的数据。

  例如:

  当您想要知道在2000年,班上前25名的学生姓名数据时,您可以输入这样的语句:

  SELECT TOP 25 学生姓名

  FORM 学生表格


  WHERE 毕业年份=1994


  ORDER BY 毕业成绩平均分数 DESC


  如果您没有加上ORDER BY 这行条件的话,您所得到的数据,将会随机的数据。此外,在TOP语句之后,除了可以加上数字以外,还可以利用保留


  字PERCENT来查询。


  例如:


  SELECT TOP 10 PERCENT学生姓名


  FROM学生表格

  WHERE毕业年份=1994


  ORDER BY毕业成绩平均DESC
 
  PARAMETERS(参数)声明的用法

  对于参数型的查询语法中,对参数的名称以及数据类型作声明的操作。


  PARAMETERS name datatype[,name datatype[,...]]


  name


  PARAMETERS的名称。您可以把参数名称当作字符串来使用,若是名称中包含了空字符串,可以利用中括号来处理,例如:“VBeden”


  datatype


  输入参数的数据类型。


  例如:


  若是您在查询时,需要机动的输入姓名,可以利用下列的方式完成:


  PARAMETERS “输入姓名” Text;


  SELECT*

  FROM 职员表格

  WHERE姓名=“输入姓名:”;

SQL,
本文章转载自 婚嫁千千缘

ORDER BY条件语句

  此条件子句,通常与SELECT语句合并使用目的是将查询的结果,依照指定字段加以排序。


  SELECT fieldlist


  FROM table


  WHERE selectcriteria


  ORDER BY field[ASC|DESC][,field2[ASC|DESC][,...]]


  fieldlist

  欲查询的字段名称。其中可以与ALLDISTINCTDISINCTROW,或TOP一起来使用。


  table


  欲查询的表格名称。


  selectcriteria


  查询的标准设置。


  field1

  指定要依照那个字段作为排序的依据,若是你没有加上ORDER BY查询出的数据集将不会作排序的操作。

  ASC

  递增顺序类别。(默认值)


  DESC

  递减顺序类别。

  例如:

  或是我们要将输出数据依据出生的先后次序排列,可以利用下面的命令。


  SELECT 姓名,生日

  FROM 职员表格


  ORDER BY 生日

  SELECT LastName,FirstName

  FROM Employees

  ORDER BY LastName ASC;

  IN 条件子句

  指定要速胜哪一个外部数据库的表格。(必须是Microsoft Jet数据库引擎所可以连接的数据库,如dBase,Paradox等等)

  
SELECT|INSERT]INTO destination IN
{path|["path" "type"]|[""[type;DATABASE=path]]}
FROM tableexpression IN
{path|["path" "type"]|[""[type;DATABASE=path]]}
destination


  欲插入数据的外部表格名称。

  tableexpression

  表格名称或是被读取数据的表格名称。这个参数可以是一个单一的表格名称,或是一段已经被存储的SQL查询等。

  path

  包含该表格的完整路径名称。

  type

  数据库的类型名称,通常是当数据库部属于Jet database时才会使用。(例如:dBASE III,dBASE IV,Paradox 3.x,Paradox 4.x, Btrieve)

  例如:下面这两段的意义相同


PartA....FROM Table
IN ""[dBASE IV;DATABASE=C:"DBASE"DATA"SALES;];

PartB....FROM Table
IN "C:"DBASE"DATA"SALES" "dBASE IV;"



  例如:Microsoft Jet database


SELECT
顾客编号
FROM
顾客表格
IN CUSTOMER.MDB
WHERE
顾客编号 Like "A*";
其中CUSTOMER.MDBO Jet database 的数据库名称,其中包含了顾客表格。

例如:dBASE III or IV
SELECT
顾客编号
FROM
顾客表格
IN "C:"DBASE"DATA"SALES" "dBASE IV;"
WHERE
顾客编号 Like "A*";
所以当我们使用不同于ACCESS 的数据库时,必须指明该数据库的类型名称。

HAVING 条件子句

  指定一特定的分组记录,并满足HAVING 所指定的条件或状态,但条件是针对分组的条件设置。


SELECT fieldlist
FROM table
WHERE selectcriteria
GROUP BY groupfieldlist
HAVING groupcriteria
fieldlist
显示被查询的字段名称。(可与ALLDISTINCTDISTINCTROW,或TOP相结合)
table
欲查询数据的表格名称。
selectcriteria
选取标准。
groupfieldlist
分组记录的字段名称,到多10个字段。而这些字段的顺序决定最高到最低的分组阶层。
groupcriteria
决定什么样的分组记录要被显示。
HAVING
WHERE 的用法相当类似,不同之处在于HAVING必须用于GROUP之后的分组数据上。
例如:
SELECT
分类编,Sum(库存数量)
FROM
产品表格
GROUP BY
分类编号
HAVING Sum(
库存数量)>100 AND 产品名称 LIKE "*"


 
  GROUP BY 条件子句

  依据指定的字段,将具有相同数值的记录合并成一条。


SELECT fieldlist
FROM table
WHERE criteria
GROUP BY groupfieldlist
fieldlist
欲读取的字段名称。(可与ALLDISTINCTDISTINCTROW,或TOP合并使用)
table
被查询的表格名称。
groupfieldlist
分组记录的字段名称,到多10个字段,而这些字段的顺序决定最高到最低的分组层次。
例如:
SELECT
姓名,Count(姓名)AS 职员姓名
FROM
职员表格
WHERE
部门名称='业务部'
GROUP BY
姓名


 
  FROM 条件子句

  指定表格名称或是查询,其中包含列在SELECT语句的字段数据。


SELECT fieldlist
FROM tableexpression[IN externaldatabase]
fieldlist
表格中的字段名称。(可与ALL,DISTINCT,DISTINCTROW,TOP相结合)
tableexpression
表格名称,或多个表格的算式。
externaldatabase
若该表格参考到外部的数据库时,将其完整的路径名称记下。
例如:
从职员表格下,查询出所有姓名字段的数据(只有姓名字段被查询,其他则不显示)
SELECT
姓名 FROM 职员表格;


 
  WHERE 条件子句

  指定查询的条件与限制。


SELECT fieldlist
FROM tableexpression
WHERE criteria
fieldlist
字段名称。(可与ALL,DISTINCT,DISTINCTROW,TOP相结合)
tableexpression
表格名称,或多个表格的算式。
criteria
查询的结果,必须依照这一限制标准。
例如:
要查询出职员表格中,所有姓氏是李的数据,可以用下面的语句。
SELECT
姓名
FROM
职员表格
WHERE
姓氏=''

posted @ 2007-09-16 07:27  魏向峰  阅读(793)  评论(0编辑  收藏  举报