一切福田,不離方寸,從心而覓,感無不通。

Category Archives: Database

mysql 添加索引

1.添加PRIMARY KEY(主键索引) mysql>ALTER TABLE table_name ADD PRIMARY KEY ( column ) 2.添加UNIQUE(唯一索引) mysql>ALTER TABLE table_name ADD UNIQUE ( column ) 3.添加INDEX(普通索引) mysql>ALTER TABLE table_name ADD INDEX index_name ( column ) 4.添加FULLTEXT(全文索引) mysql>ALTER TABLE table_name ADD FULLTEXT ( column) 5.添加多列索引 mysql>ALTER TABLE table_name ADD INDEX index_name ( column1, column2, column3 ) 转自:http://www.jb51.net/article/32149.htm

龙生   15 Mar 2013
View Details

with(nolock)详解

大家在写查询时,为了性能,往往会在表后面加一个nolock,或者是with(nolock),其目的就是查询是不锁定表,从而达到提高查询速度的目的。 什么是并发访问:同一时间有多个用户访问同一资源,并发用户中如果有用户对资源做了修改,此时就会对其它用户产生某些不利的影响,例如: 1:脏读,一个用户对一个资源做了修改,此时另外一个用户正好读取了这条被修改的记录,然后,第一个用户放弃修改,数据回到修改之前,这两个不同的结果就是脏读。 2:不可重复读,一个用户的一个操作是一个事务,这个事务分两次读取同一条记录,如果第一次读取后,有另外用户修改了这个数据,然后第二次读取的数据正好是其它用户修改的数据,这样造成两次读取的记录不同,如果事务中锁定这条记录就可以避免。 3:幻读,指用户读取一批记录的情况,用户两次查询同一条件的一批记录,第一次查询后,有其它用户对这批数据做了修改,方法可能是修改,删除,新增,第二次查询时,会发现第一次查询的记录条目有的不在第二次查询结果中,或者是第二次查询的条目不在第一次查询的内容中。 为什么会在查询的表后面加nolock标识?为了避免并发访问产生的不利影响,SQL Server有两种并发访问的控制机制:锁、行版本控制,表后面加nolock是解决并发访问的方案之一。 1> 锁,每个事务对所依赖的资源会请求不同类型的锁,它可以阻止其他事务以某种可能会导致事务请求锁出错的方式修改资源。当事务不再依赖锁定的资源时,锁将被释放。 锁的类型:1:表类型:锁定整个表;2:行类型:锁定某个行;3:文件类型:锁定某个数据库文件;4:数据库类型:锁定整个数据库;5:页类型:锁定8K为单位的数据库页。 锁的分类还有一种分法,就是按用户和数据库对象来分: 1). 从数据库系统的角度来看:分为独占锁(即排它锁),共享锁和更新锁 1:共享 (S) :用于不更改或不更新数据的操作(只读操作),一般常见的例如select语句。 2:更新 (U) :用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。 3:排它 (X) :用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。确保不会同时同一资源进行多重更新。 2). 从程序员的角度看:分为乐观锁和悲观锁。 1:乐观锁:完全依靠数据库来管理锁的工作。 2:悲观锁:程序员自己管理数据或对象上的锁处理。 一般程序员一看到什么锁之类,觉的特别复杂,对专业的DBA当然是入门级知识了。可喜的是程序员不用去设置,控制这些锁,SQLServer通过设置事务的隔离级别自动管理锁的设置和控制。锁管理器通过查询分析器分析待执行的sql语句,来判断语句将会访问哪些资源,进行什么操作,然后结合设定的隔离级别自动分配管理需要用到的锁。 2>:行版本控制:当启用了基于行版本控制的隔离级别时,数据库引擎 将维护修改的每一行的版本。应用程序可以指定事务使用行版本查看事务或查询开始时存在的数据,而不是使用锁保护所有读取。通过使用行版本控制,读取操作阻止其他事务的可能性将大大降低。也就是相当于针对所有的表在查询时都会加上nolock,同样会产生脏读的现象,但差别在于在一个统一管理的地方。说到了基于行版本控制的隔离级别,这里有必要说下隔离级别的概念。 隔离级别的用处:控制锁的应用,即什么场景应用什么样的锁机制。 最终目的:解决并发处理带来的种种问题。 隔离级别的分类: 1:未提交读,隔离事务的最低级别,只能保证不读取物理上损坏的数据; 2:已提交读,数据库引擎的默认级; 3:可重复读; 4:可序列化;隔离事务的最高级别,事务之间完全隔离。 小结:NOLOCK 语句执行时不发出共享锁,允许脏读 ,等于 READ UNCOMMITTED事务隔离级别 。nolock确实在查询时能提高速度,但它并不是没有缺点的,起码它会引起脏读。 nolock的使用场景(个人观点): 1:数据量特别大的表,牺牲数据安全性来提升性能是可以考虑的; 2:允许出现脏读现象的业务逻辑,反之一些数据完整性要求比较严格的场景就不合适了,像金融方面等。 3:数据不经常修改的表,这样会省于锁定表的时间来大大加快查询速度。 综上所述,如果在项目中的每个查询的表后面都加nolock,这种做法并不科学,起码特别费时间,不如行版本控制来的直接有效。而且会存在不可预期的技术问题。应该有选择性的挑选最适合的表来放弃共享锁的使用。 最后说下nolock和with(nolock)的几个小区别: 1:SQL05中的同义词,只支持with(nolock); 2:with(nolock)的写法非常容易再指定索引。 跨服务器查询语句时 不能用with (nolock) 只能用nolock 同一个服务器查询时 则with (nolock)和nolock都可以用 比如 SQL code select * from [IP].a.dbo.table1 with (nolock) 这样会提示用错误select * from a.dbo.table1 with (nolock) 这样就可以 转自:http://hi.baidu.com/gabriel/item/11f32132593557c31a96961a

龙生   15 Mar 2013
View Details

MySql Error Code: 2006 – MySQL 服务器已离线

用SQLYog进行数据导入的时候出错:MySql Error Code: 2006 – MySQL 服务器已离线 解决: 1.在mysql的配置文件最后添加:max_allowed_packet = 100M 2.如果还不行,就再添加以下两行: interactive_timeout=28800000 wait_timeout=28800000

龙生   09 Mar 2013
View Details

mySQL错误: The used table type doesn’t support FULLTEXT indexes

  mySQL错误: The used table type doesn’t support FULLTEXT indexes 说明不支持全文索引 解决方法有两种,网上大多方法是: 1.打开my.ini,搜索default-storage-engine=,你搜索到的应该是 default-storage-engine=INNODB,把INNODB改成MyISAM,然后重新启动Mysql 这样所有的表都支持全文索引了。 2.如果你只想某张表具有全文索引,这只需要要把表的type改成MyISAM 具体做法如下: ALTER TABLE 表名 TYPE = MyISAM; 或者你和我一样用了navicat工具: 可以在选择-》设计表-》选项 在表类型中改成MyISAM即可。 如果大家用上述方法碰到问题,欢迎大家和我交流,我及时更正。 转自:http://www.cnblogs.com/liveandevil/archive/2012/08/10/2631601.html  

龙生   19 Feb 2013
View Details

MySQL 时区设置

  MySQL 时区默认是服务器的时区。 可以通过以下命令查看 SQL代码 mysql> show variables like ‘%time_zone%’;+——————+——–+| Variable_name    | Value  |+——————+——–+| system_time_zone | CST    || time_zone        | SYSTEM |+——————+——–+2 rows in set (0.00 sec) 可以通过修改my.cnf在 [mysqld] 之下加 default-time-zone=timezone来修改时区。如:default-time-zone = ‘+8:00′改了记得重启msyql喔注意一定要在 [mysqld] 之下加 ,否则会出现 unknown variable ‘default-time-zone=+8:00′ 另外也可以通过命令 set time_zone = timezone比如北京时间(GMT+0800)set time_zone = ‘+8:00′;这个和php的时区设置又有点差别,比如北京时间在php中是date_default_timezone_set(‘Etc/GMT-8′); 美国pst时间(GMT-08:00)set time_zone = ‘-8:00′; SQL代码 mysql> set time_zone = ‘+8:00′;Query OK, 0 rows affected (0.00 sec)   mysql> select now();+———————+| now()               |+———————+| 2008-12-29 11:26:36 |+———————+1 row in set (0.00 sec) mysql> set time_zone = ‘-8:00′;Query OK, 0 rows affected (0.00 sec) mysql> select now();+———————+| now()               |+———————+| 2008-12-28 19:27:09 |+———————+1 row in set (0.00 sec) 定义函数: function set_time_zone(){mysql_query(“set time_zone = ‘+8:00′;”);$sql=mysql_query(“select now() as now”);$r=mysql_fetch_array($sql);return $r['now'];} 转自:http://www.majormoves.net/post/441/  

龙生   19 Feb 2013
View Details

Mysql常用命令行大全

  第一招、mysql服务的启动和停止 net stop mysql net start mysql 第二招、登陆mysql 语法如下: mysql -u用户名 -p用户密码 键入命令mysql -uroot -p, 回车后提示你输入密码,输入12345,然后回车即可进入到mysql中了,mysql的提示符是: mysql> 注意,如果是连接到另外的机器上,则需要加入一个参数-h机器IP 第三招、增加新用户 格式:grant 权限 on 数据库.* to 用户名@登录主机 identified by “密码” 如,增加一个用户user1密码为password1,让其可以在本机上登录, 并对所有数据库有查询、插入、修改、删除的权限。首先用以root用户连入mysql,然后键入以下命令: grant select,insert,update,delete on *.* to user1@localhost Identified by “password1″; 如果希望该用户能够在任何机器上登陆mysql,则将localhost改为”%”。 如果你不想user1有密码,可以再打一个命令将密码去掉。 grant select,insert,update,delete on mydb.* to user1@localhost identified by “”; 第四招: 操作数据库 登录到mysql中,然后在mysql的提示符下运行下列命令,每个命令以分号结束。 1、 显示数据库列表。 show databases; 缺省有两个数据库:mysql和test。 mysql库存放着mysql的系统和用户权限信息,我们改密码和新增用户,实际上就是对这个库进行操作。 2、 显示库中的数据表: use mysql; show tables; 3、 显示数据表的结构: describe 表名; 4、 建库与删库: create database 库名; drop database 库名; 5、 建表: use 库名; create table 表名(字段列表); drop table 表名; 6、 清空表中记录: delete from 表名; 7、 显示表中的记录: select * from 表名; 第五招、导出和导入数据 1. 导出数据: mysqldump –opt test > mysql.test 即将数据库test数据库导出到mysql.test文件,后者是一个文本文件 如:mysqldump -u root -p123456 –databases dbname > mysql.dbname 就是把数据库dbname导出到文件mysql.dbname中。 2. 导入数据: mysqlimport -u root -p123456 < mysql.dbname。 不用解释了吧。 3. 将文本数据导入数据库: 文本数据的字段数据之间用tab键隔开。 use test; load data local infile “文件名” into table 表名; 1:使用SHOW语句找出在服务器上当前存在什么数据库: mysql> SHOW DATABASES; 2:2、创建一个数据库MYSQLDATA mysql> CREATE DATABASE MYSQLDATA; 3:选择你所创建的数据库 mysql> USE MYSQLDATA; (按回车键出现Database changed 时说明操作成功!) 4:查看现在的数据库中存在什么表 mysql> SHOW TABLES; 5:创建一个数据库表 mysql> CREATE TABLE MYTABLE (name VARCHAR(20), sex CHAR(1)); 6:显示表的结构: mysql> DESCRIBE MYTABLE; 7:往表中加入记录 mysql> insert into MYTABLE values (“hyq”,”M”); 8:用文本方式将数据装入数据库表中(例如D:/mysql.txt) mysql> LOAD DATA LOCAL INFILE “D:/mysql.txt” INTO TABLE MYTABLE; 9:导入.sql文件命令(例如D:/mysql.sql) mysql>use database; mysql>source d:/mysql.sql; 10:删除表 mysql>drop TABLE MYTABLE; 11:清空表 mysql>delete from MYTABLE; 12:更新表中数据 mysql>update MYTABLE set sex=”f” where name=’hyq’; posted on 2006-01-10 16:21 happytian 阅读(6) 评论(0) 编辑 收藏 收藏至365Key 13:备份数据库 mysqldump -u root 库名>xxx.data 14:例2:连接到远程主机上的MYSQL 假设远程主机的IP为:110.110.110.110,用户名为root,密码为abcd123。则键入以下命令: mysql -h110.110.110.110 -uroot -pabcd123 (注:u与root可以不用加空格,其它也一样) 3、退出MYSQL命令: exit (回车)  

龙生   19 Feb 2013
View Details

SQL中Case的使用方法

  Case具有两种格式。简单Case函数和Case搜索函数。 –简单Case函数 CASE sex          WHEN ’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 下面我们来看一下,使用Case函数都能做些什么事情。 一,已知数据按照另外一种方式进行分组,分析。 有如下数据:(为了看得更清楚,我并没有使用国家代码,而是直接用国家名作为Primary Key) 国家(country)人口(population) 中国600 美国100 加拿大100 英国200 法国300 日本250 德国200 墨西哥50 印度250 根据这个国家人口数据,统计亚洲和北美洲的人口数量。应该得到下面这个结果。 洲人口 亚洲1100 北美洲250 其他700 想要解决这个问题,你会怎么做?生成一个带有洲Code的View,是一个解决方法,但是这样很难动态的改变统计的方式。 如果使用Case函数,SQL代码如下: SELECT SUM(population),         CASE country                 WHEN ’中国’     THEN ’亚洲’                 WHEN ’印度’     THEN ’亚洲’                 WHEN ’日本’     THEN ’亚洲’                 WHEN ’美国’     THEN ’北美洲’                 WHEN ’加拿大’ THEN ’北美洲’                 WHEN ’墨西哥’ THEN ’北美洲’         ELSE ’其他’ END FROM    Table_A GROUP BY CASE country                 WHEN ’中国’     THEN ’亚洲’                 WHEN ’印度’     THEN ’亚洲’                 WHEN ’日本’     THEN ’亚洲’                 WHEN ’美国’     THEN ’北美洲’                 WHEN ’加拿大’ THEN ’北美洲’                 WHEN ’墨西哥’ THEN ’北美洲’         ELSE ’其他’ END; 同样的,我们也可以用这个方法来判断工资的等级,并统计每一等级的人数。SQL代码如下; SELECT         CASE 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_A GROUP BY         CASE 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语句会比较长。 […]

龙生   19 Feb 2013
View Details

写出高性能SQL语句的十三条法则

  1、 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用“全表扫描”方式。 可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“执行计划”有两点很重要: (1)    SQL语句是否清晰地告诉查询优化器它想干什么? (2)    查询优化器得到的数据库统计信息是否是最新的、正确的? 2、 统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。 select * from dual select * From dual 其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行! 3、 不要把SQL语句写得太复杂 我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。 一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。 另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。 4、 使用“临时表”暂存中间结果 简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。 5、 OLTP系统SQL语句必须采用绑定变量 select * from orderheader where changetime > ‘2010-10-20 00:00:01’ select * from orderheader where changetime > ‘2010-09-22 00:00:01’ 以上两句语句,查询优化器认为是不同的SQL语句,需要解析两次。如果采用绑定变量 select * from orderheader where changetime > @chgtime @chgtime变量可以传入任何值,这样大量的类似查询可以重用该执行计划了,这可以大大降低数据库解析SQL语句的负担。一次解析,多次重用,是提高数据库效率的原则。 6、 绑定变量窥测 事物都存在两面性,绑定变量对大多数OLTP处理是适用的,但是也有例外。比如在where条件中的字段是“倾斜字段”的时候。 “倾斜字段”指该列中的绝大多数的值都是相同的,比如一张人口调查表,其中“民族”这列,90%以上都是汉族。那么如果一个SQL语句要查询30岁的汉族人口有多少,那“民族”这列必然要被放在where条件中。这个时候如果采用绑定变量@nation会存在很大问题。 试想如果@nation传入的第一个值是“汉族”,那整个执行计划必然会选择表扫描。然后,第二个值传入的是“布依族”,按理说“布依族”占的比例可能只有万分之一,应该采用索引查找。但是,由于重用了第一次解析的“汉族”的那个执行计划,那么第二次也将采用表扫描方式。这个问题就是著名的“绑定变量窥测”,建议对于“倾斜字段”不要采用绑定变量。 7、 只在必要的情况下才使用begin tran SQL Server中一句SQL语句默认就是一个事务,在该语句执行完成后也是默认commit的。其实,这就是begin tran的一个最小化的形式,好比在每句语句开头隐含了一个begin tran,结束时隐含了一个commit。 有些情况下,我们需要显式声明begin tran,比如做“插、删、改”操作需要同时修改几个表,要求要么几个表都修改成功,要么都不成功。begin tran 可以起到这样的作用,它可以把若干SQL语句套在一起执行,最后再一起commit。好处是保证了数据的一致性,但任何事情都不是完美无缺的。Begin tran付出的代价是在提交之前,所有SQL语句锁住的资源都不能释放,直到commit掉。 可见,如果Begin tran套住的SQL语句太多,那数据库的性能就糟糕了。在该大事务提交之前,必然会阻塞别的语句,造成block很多。 Begin tran使用的原则是,在保证数据一致性的前提下,begin tran 套住的SQL语句越少越好!有些情况下可以采用触发器同步数据,不一定要用begin tran。 8、 一些SQL查询语句应加上nolock 在SQL语句中加nolock是提高SQL Server并发性能的重要手段,在oracle中并不需要这样做,因为oracle的结构更为合理,有undo表空间保存“数据前影”,该数据如果在修改中还未commit,那么你读到的是它修改之前的副本,该副本放在undo表空间中。这样,oracle的读、写可以做到互不影响,这也是oracle广受称赞的地方。SQL Server 的读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用nolock有3条原则。 (1)    查询的结果用于“插、删、改”的不能加nolock ! (2)    查询的表属于频繁发生页分裂的,慎用nolock ! (3)    使用临时表一样可以保存“数据前影”,起到类似oracle的undo表空间的功能, 能采用临时表提高并发性能的,不要用nolock 。 9、 聚集索引没有建在表的顺序字段上,该表容易发生页分裂 比如订单表,有订单编号orderid,也有客户编号contactid,那么聚集索引应该加在哪个字段上呢?对于该表,订单编号是顺序添加的,如果在orderid上加聚集索引,新增的行都是添加在末尾,这样不容易经常产生页分裂。然而,由于大多数查询都是根据客户编号来查的,因此,将聚集索引加在contactid上才有意义。而contactid对于订单表而言,并非顺序字段。 比如“张三”的“contactid”是001,那么“张三”的订单信息必须都放在这张表的第一个数据页上,如果今天“张三”新下了一个订单,那该订单信息不能放在表的最后一页,而是第一页!如果第一页放满了呢?很抱歉,该表所有数据都要往后移动为这条记录腾地方。 SQL Server的索引和Oracle的索引是不同的,SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序,相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式,所以它的效率是非常高的。也正因为此,插入一条记录,它的位置不是随便放的,而是要按照顺序放在该放的数据页,如果那个数据页没有空间了,就引起了页分裂。所以很显然,聚集索引没有建在表的顺序字段上,该表容易发生页分裂。 曾经碰到过一个情况,一位哥们的某张表重建索引后,插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上,该表经常被归档,所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单,而最近3个月的订单只有5张,归档策略是保留3个月数据,那么张三过去的15张订单已经被归档,留下15个空位,可以在insert发生时重新被利用。在这种情况下由于有空位可以利用,就不会发生页分裂。但是查询性能会比较低,因为查询时必须扫描那些没有数据的空位。 重建聚集索引后情况改变了,因为重建聚集索引就是把表中的数据重新排列一遍,原来的空位没有了,而页的填充率又很高,插入数据经常要发生页分裂,所以性能大幅下降。 对于聚集索引没有建在顺序字段上的表,是否要给与比较低的页填充率?是否要避免重建聚集索引?是一个值得考虑的问题! 10、加nolock后查询经常发生页分裂的表,容易产生跳读或重复读 加nolock后可以在“插、删、改”的同时进行查询,但是由于同时发生“插、删、改”,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复读到该条数据,产生“重复读”。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生“跳读”。 上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。 11、使用like进行模糊查询时应注意 有的时候会需要进行一些模糊查询比如 select * from contact where username like ‘%yue%’ 关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%, 12、数据类型的隐式转换对查询效率的影响 sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。 13、SQL Server 表连接的三种方式 (1) Merge Join (2) Nested Loop Join (3) Hash Join SQL Server 2000只有一种join方式——Nested Loop Join,如果A结果集较小,那就默认作为外表,A中每条记录都要去B中扫描一遍,实际扫过的行数相当于A结果集行数x B结果集行数。所以如果两个结果集都很大,那Join的结果很糟糕。 SQL Server 2005新增了Merge Join,如果A表和B表的连接字段正好是聚集索引所在字段,那么表的顺序已经排好,只要两边拼上去就行了,这种join的开销相当于A表的结果集行数加上B表的结果集行数,一个是加,一个是乘,可见merge join 的效果要比Nested Loop Join好多了。 如果连接的字段上没有索引,那SQL2000的效率是相当低的,而SQL2005提供了Hash join,相当于临时给A,B表的结果集加上索引,因此SQL2005的效率比SQL2000有很大提高,我认为,这是一个重要的原因。 总结一下,在表连接时要注意以下几点: (1)    连接字段尽量选择聚集索引所在的字段 (2)    仔细考虑where条件,尽量减小A、B表的结果集 (3)    如果很多join的连接字段都缺少索引,而你还在用SQL Server 2000,赶紧升级吧。 原文链接:http://www.cnblogs.com/shuzhengyi/archive/2011/02/12/1952481.html

龙生   19 Feb 2013
View Details

SQL server的一道入门面试题背后的思考

  最近看到一个SQL Server的小例子,发现完全可以作为SQL server的一道入门面试题。题目如下: 例:有一合同表Contract Id Name Total buget 1 合同名称 100  102,22 2 合同名称2 300 ,102,22, 3 合同名称3 200  103,23, 要求:用SQL语句更新表的buget字段,如果前后没有”,”要加上”,”(即一个英文逗号)。(10分) 创建表数据: View Code use Testdb2 go IF NOT OBJECT_ID(‘[Contract]‘) ISNULL DROPTABLE [Contract] GO Createtable [Contract] (ID intprimarykey identity(1,1) ,[Name] nvarchar(50) null ,Total floatnull ,buget Nvarchar(500) null ) go insertinto [Contract] select‘合同名称’,  100,’102,22′ unionall select‘合同名称2′, 300,‘,102,22,’ unionall select‘合同名称3′, 300,’101,23,’  分析:这道题乍看很简单,由于肯定用到Replace,所以很自然的结合left,right,从而得到以下语句 方法一: update [Contract] set buget=‘,’+buget whereleft(buget,1)=‘,’ update [Contract] set buget=buget+‘,’whereright(buget,1)=‘,’ 如果能写成一个 SQL语句,可以加1分。 update [Contract] set buget=(casewhen (left(buget,1)!=‘,’andright   (buget,1)!=‘,’) then‘,’+buget+‘,’ whenleft(buget,1)!=‘,’then‘,’+buget whenright(buget,1)!=‘,’then  buget+‘,’ else buget end) 如果能从字符串的开关和结尾这个思路出发,结合Reverse,可以提到如下方法: 方法二: update [Contract] set buget=‘,’+buget where charindex(‘,’,buget)<>1 update [Contract] set buget=buget+‘,’where charindex(‘,’,reverse(buget))<>1 该方法,主要涉及charindex函数和reverse函数。 说实话,我当时就这两种思路,这也是SQL中常见的基本用法。但出人意料的第三种方法出现了。 方法三: UPDATE [contract] SET Buget = ‘,’+Buget+‘,’ UPDATE [contract] SET Buget = REPLACE(Buget,‘,,’,‘,’) 解析:该方法最主要的亮点不在于语法的精妙,而在于其思路的异于常规。先给两边补上逗号,再替换双逗号为单逗号。这在实际编程中确实难能可贵。换句话说,如果没有事先思考过的话,这反映了解题者反应敏捷,思路开放。因此,至少可以再加3分。 当然,此语句其实还是有bug,比如如果原bug字段中间有两个逗号,那么在Replace时就会更新掉不应该更新的内容。不过,稍加修正,限定replace的范围即可, 受此思路启发,可以引申得到以下类似方法: 方法四: UPDATE [contract] SET Buget = substring(BuGet,2,len(BuGet)-1) wherecharindex(‘,’,buget)=1 UPDATE [contract] SET Buget = substring(BuGet,1,len(BuGet)-1) wherecharindex(‘,’,reverse(buget))=1 UPDATE [contract] SET BuGet = ‘,’+BuGet+‘,’ 该方法是先去掉两边的逗号,再给每条记录加上逗号,比起方法三来,稍显繁琐,这也反衬了方法三的巧妙。 当然,也可以结合前面的思路稍作修正,这里就不再赘述,请读者自己思考。 感悟:释迦牟尼说过“人生需要经过六项修炼:布施、持戒、忍辱、精进、禅定、智慧。”,SQL编程,或C#、Java,甚至Javascrip的某个领域也是如此。技术是死的,思路是鲜活的,有时候,思路能轻易地突破技术很难实现的死角。到了一定程度时,会发现潜意识里已经被惯性思维塞满,而无法接受新鲜思维方式或思路,如果一段时间内持续如此,那么,我们应该警醒,把自己的头脑放空,把自己置于一个初学者的地位,重新开始“精进”的修炼! 原文链接:http://www.cnblogs.com/downmoon/archive/2011/03/02/1968615.html  

龙生   19 Feb 2013
View Details

如何查看mysql里的编码格式,以及如何修改

  首先进入dos模式下输入: 1.cd C:\Program Files\MySQL\MySQL Server 5.5\bin 2.mysql -h127.0.0.1(你要访问的主机的地址) -uroot(用户名) -proot(密码)  3.show variables like ‘character%’; 这样就完成了对你的mysql里的编码格式的查看了,如果你想修改,继续执行下面的步骤: 打开mysql安装目录,里面有个my.ini文件,打开这个文件,里面有两处字符集的设置,默认是拉丁,建议你所想改的,如:utf8或gbk 然后启动mysql服务,以后创建的数据库默认字符集就是ok了 (重启时,打开MySQLAdministrator的Service Control进行操作就可以了。)  

龙生   19 Feb 2013
View Details
1 34 35 36 40