新阵列移动日
问:我们当前的 RAID 很快就填满了,因此需要将一些 SQL Server 2005 数据库移到其他位置。新阵列已准备就绪,并且我一直在为移动数据库作准备。我刚刚发现其中一个数据库是事务复制发布 服务器 ,我知道这表示我不能移动该数据库。我应怎样做?
答:对您来说有一个好消息 - 只有 SQL Server 2000(和更早版本)具有以下局限性:限制在未重新初始化事务复制或直接更改各种系统表的情况下移动发布数据库。
对于 SQL Server 2005 和 SQL Server 2008,有一个记录下来的过程,您可以按照它移动数据库,而不必对事务复制执行任何操作,但要求数据库保持连接到同一 SQL Server 实例。移动时必须停机一段时间,因为当数据库文件仍处于联机状态时无法将其移动。过程如下:
首先,使用下面的代码使数据库脱机。如果有用户连接到数据库,则需要先断开这些用户的连接,此过程才能成功:
接着,将数据文件复制到新位置。使用复制而不是移动,可在发生任何错误时进行快速回滚(否则,必须执行还原)。然后,使用以下代码告知 SQL Server 每个文件的新位置
物理上复制了所有文件并更新了 SQL Server 中的文件位置后,使用以下代码使数据库恢复联机状态:
关闭页锁存

问:我在理解一些性能优化相关概念时存在疑问。我几次读到需要防止“页锁存”问题。我不知道“页”或“锁存”是什么意思,或者说为什么页锁存甚至是一个问题。您能解释所有这些疑问吗?
答:SQL Server 数据库中的所有数据都存储在数据文件中。在内部,这些文件组织成大小为 8 KB 的数据块序列,称为页。页是 SQL Server 可以管理的基本存储和 I/O 单位。页通常位于磁盘上的数据文件中,并且在处理任何查询之前,需要 SQL Server 的缓存(称为缓冲池)来进行读取。
SQL Server 使用各种页来存储不同类型的关系数据(例如,表中的行、非群集索引中的行或者文本/LOB 数据)。还有一些页存储 SQL Server 组织和访问存储关系数据的页所需的内部数据结构部分。
锁存 是一种轻量级内部机制,SQL Server 使用它来同步对缓存内的某个页的访问。您需要注意两种类型的页锁存 - 常规页锁存 和页 I/O 锁存。如果 SQL Server 线程必须等待获取其中一个锁存,则表示出现性能问题。
当 SQL Server 正等待从磁盘中读取数据文件的某部分时,则可能会导致页 I/O 锁存等待。如果页 I/O 锁存持续很长时间,则通常表明底层磁盘子系统出现性能问题(即,该子系统过载)。
当 SQL Server 中的多个线程尝试访问内存中的相同 8 KB 数据文件页时,就存在对该页访问权的争用,这可能会导致页锁存等待。最常见的这种情况涉及大量使用 tempdb 数据库中的临时小对象。
有关如何监视和减少页锁存等待的更深入说明不属于本专栏文章的范围,但您可以在以下资料中找到更多信息:
SQL Server 2008 联机丛书中的“SQL Server Wait Statistics 对象”部分,它说明如何使用系统监视器监视等待统计数据。
SQL Server 2008 联机丛书中的“sys.dm_os_wait_stats”部分,它列出了常见的 SQL Server 等待类型及其含义,并说明如何从 SQL Server 内部监视等待统计数据。
白皮书《SQL Server 2008 中的性能问题故障排除》,它提供各种故障排除查询和技术,包括等待统计数据。
通查数据库快照
问:我刚刚发现了数据库快照。现在,我考虑将它们用作完全恢复模式和日志备份的替代方法。我将大约每小时创建一次快照,这样当出现错误时,我可以拉回损坏的数据。这似乎是一种更省事且更快的还原方法。您认为进行这种更改会产生任何问题吗?
答:会产生问题,数据库快照不是全面的灾难恢复策略的实用或可行替代方法。在从灾难完全恢复方面,数据库快照不具备与事务日志备份相同的功能。数据库快照不包含数据库中所有页的副本,它只包含自***次创建数据库后更改过的页的副本。这意味着,如果数据库有任何损坏,则没有底层数据库的数据库快照将没有任何用处。它只是数据库中不同页的集合,不能用于恢复。
您可以通过数据库快照拉回不小心从数据库中删除的数据,但前提是数据库本身仍可用。例如,如果从数据库中删除的表仍存在于快照中,则可以使用快照重新创建该表。
也就是因为潜在的性能问题,创建太多数据库快照(作为每一个半小时的事务日志备份的替代方法)不是一个好主意。在可以交换数据库页之前(请参阅“关闭页锁存”部分中的答案说明),必须先将页同步地复制到尚未包含该页版本的所有现有数据库快照中。随着创建的数据库快照越来越多,要生成的页副本也越来越多,从而导致性能下降。
不要创建太多数据库快照的另一个原因是每个数据库快照将包含数据库页更改前的副本。每个副本将随着数据库中更改的内容增多而增大。这可能会导致磁盘空间问题和性能问题。
数据库快照不是为了替代频繁日志备份而设计的。您可以在白皮书>
sql怎么使用case when
Case具有两种格式。 简单Case函数和Case搜索函数。 –简单Case函数CASE sexWHEN ’1′ TheN ’男’WHEN ’2′ THEN ’女’ELSE ’其他’ END–Case搜索函数CASE WHEN sex = ’1′ THEN ’男’WHEN sex = ’2′ THEN ‘女’ELSE ‘其他’ END这两种方式,可以实现相同的功能。 简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式。 还有一个需要注意的问题,Case函数只返回第一个符合条件的值,剩下的Case部分将会被自动忽略。 –比如说,下面这段SQL,将永远无法得到“第二类”这个结果CASE WHEN col_1 IN (‘a’, ‘b’) THEN ’第一类’WHEN col_1 IN (‘a’) THEN ’第二类’ELSE’其他’ END一,已知数据按照另外一种方式进行分组,分析。 有如下数据:(用国家名作为Primary Key)国家(country)人口(population)中国 600美国 100加拿大 100英国 200法国 300日本 250德国 200墨西哥 50印度 250根据这个国家人口数据,统计亚洲和北美洲的人口数量。 应该得到下面这个结果。 洲 人口亚洲 1100北美洲 250其他 700想要解决这个问题,生成一个带有洲的View,是一个解决方法具有两种格式。 简单Case函数和Case搜索函数。 –简单Case函数CASE sexWHEN ’1′ THEN ’男’WHEN ’2′ THEN ’女’ELSE ’其他’ END–Case搜索函数CASE WHEN sex = ’1′ THEN ’男’WHEN sex = ’2′ THEN ‘女’ELSE ‘其他’ END这两种方式,可以实现相同的功能。 简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式。 还有一个需要注意的问题,Case函数只返回第一个符合条件的值,剩下的Case部分将会被自动忽略。 –比如说,下面这段SQL,将永远无法得到“第二类”这个结果CASE WHEN col_1 IN (‘a’, ‘b’) THEN ’第一类’WHEN col_1 IN (‘a’) THEN ’第二类’ELSE’其他’ END一,已知数据按照另外一种方式进行分组,分析。 有如下数据:(用国家名作为Primary Key)国家(country)人口(population)中国 600美国 100加拿大 100英国 200法国 300日本 250德国 200墨西哥 50印度 250根据这个国家人口数据,统计亚洲和北美洲的人口数量。 应该得到下面这个结果。 洲 人口亚洲 1100北美洲 250其他 700想要解决这个问题,生成一个带有洲的View,是一个解决方法,但是这样很难动态的改变统计的方式。 如果使用Case函数,SQL代码如下:SELECT SUM(population),CASE countryWHEN ‘中国’ THEN ‘亚洲’WHEN ’印度’ THEN ’亚洲’WHEN ’日本’ THEN ’亚洲’WHEN ’美国’ THEN ’北美洲’WHEN ‘加拿大’ THEN ’北美洲’WHEN ’墨西哥’ THEN ‘北美洲’ELSE ‘其他’ ENDFROM Table_AGROUP BY CASE countryWHEN ’中国’ THEN ’亚洲’WHEN ‘印度’ THEN ’亚洲’WHEN ’日本’ THEN ‘亚洲’WHEN ’美国’ THEN ’北美洲’WHEN ’加拿大’ THEN ’北美洲’WHEN ‘墨西哥’ THEN ’北美洲’ELSE ’其他’ END;同样也可以用这个方法来判断工资的等级,并统计每一等级的人数。 SQL代码如下;SELECTCASE WHEN salary <= 500 THEN ’1′WHEN salary > 500 AND salary <= 600 THEN ’2′WHEN salary > 600 AND salary <= 800 THEN ’3′WHEN salary > 800 AND salary <= 1000 THEN ’4′ELSE NULL END salary_class,COUNT(*)FROM Table_AGROUP BYCASE WHEN salary <= 500 THEN ’1′WHEN salary > 500 AND salary <= 600 THEN ’2′WHEN salary > 600 AND salary <= 800 THEN ’3′WHEN salary > 800 AND salary <= 1000 THEN ’4′ELSE NULL END;二,用一个SQL语句完成不同条件的分组。 有如下数据国家(country)性别(sex)人口(population)中国 1 340中国 2 260美国 1 45美国 2 55加拿大 1 51加拿大 2 49英国 1 40英国 2 60按照国家和性别进行分组,得出结果如下国家 男 女中国 340 260美国 45 55加拿大 51 49英国 40 60普通情况下,用UNION也可以实现用一条语句进行查询。 但是那样增加消耗(两个Select部分),而且SQL语句会比较长。 下面是一个是用Case函数来完成这个功能的例子SELECT country,SUM( CASE WHEN sex = ’1′ THENpopulation ELSE 0 END), –男性人口SUM( CASE WHEN sex = ’2′ THENpopulation ELSE 0 END) –女性人口FROM Table_AGROUP BY country;这样使用Select,完成对二维表的输出形式,充分显示了Case函数的强大。 三,在Check中使用Case函数。 在Check中使用Case函数在很多情况下都是非常不错的解决方法。 可能有很多人根本就不用Check,建议在看过下面的例子之后也尝试一下在SQL中使用Check。 举个例子,公司A有个规定,女职员的工资必须高于1000块。 如果用Check和Case来表现的话,如下所示CONSTRAINT check_salary CHECK( CASE WHEN sex = ’2′THEN CASE WHEN salary > 1000THEN 1 ELSE 0 ENDELSE 1 END = 1 )如果单纯使用Check,如下所示CONSTRAINT check_salary CHECK( sex = ’2′ AND salary > 1000 )女职员的条件倒是符合了,男职员的数据就无法输入了。
求:从查询结果里,再查询最小值的SQL语句
答案如下:SELECT TOP 1 year,month FROM[你的表名] ORDER BYver,year,month分析的思路:从题目上看,要求查询的ver year month都要求是查询最小值,那么我们能想到查询最小值的方法有很多,其中最简便的一种思路就是从小到大排序,然后我们取出第一个,不就是我们需要的最小值了么,有这个思路,就直接对ver year month都排序(DESC是降序排列,ASC是升序,一般我们在ORDER BY 后不写的时候,默认就是ASC),取第一行的值,那么就是TOP 1,由此得出我们的答案。 遇到问题以后,学会“切片”来分析,它需要干什么,你就找对应的方法,然后把这些方案串起来,就可以解决问题啦。 拿本题来说:(1):找到最小值的方法:从小到大排序,最小值就出来了。 (2):怎么拿到最小值,TOP 1 拿到第一行也就等同于拿到最小值。 希望可以帮助到你,^_~
SQL语句搜索问题
strSQL=SELECT * FROM 表 WHERE 字段=必须的条件if 选择条件1 thenstrSQL+=AND 字段1=‘条件1’endifif 选择条件1 thenstrSQL+=AND 字段2=‘条件2“endif........
发表评论