事务的四大特征: ACID:Atomic(原子性)、Consistent(一致性)、Isolated(独立性)、Durable (持久性) MySQL的事务支持不是绑定在MySQL服务器本身,而是与存储引擎相关: sql代码 1. MyISAM:不支持事务,用于只读程序提高性能 2. InnoDB:支持ACID事务、行级锁、并发 3. Berkeley DB:支持事务 事务隔离级别标准: ANSI(美国国家标准学会)标准定义了4个隔离级别,MySQL的InnoDB都支持: sql代码 1. READ UNCOMMITTED:最低级别的隔离,通常又称为dirty read,它允许一个事务读取还没commit的数据,这样可能会提高性能,但是dirty read可能不是我们想要的 2. READ COMMITTED:在一个事务中只允许已经commit的记录可见,如果session中select还在查询中,另一session此时insert一条记录,则新添加的数据不可见 3. REPEATABLE READ:在一个事务开始后,其他session对数据库的修改在本事务中不可见,直到本事务commit或rollback。在一个事务中重复select的结果一样,除非本事务中update数据库。 4. SERIALIZABLE:最高级别的隔离,只允许事务串行执行。为了达到此目的,数据库会锁住每行已经读取的记录,其他session不能修改数据直到前一事务结束,事务commit或取消时才释放锁。 Mysql的默认隔离级别是:REPEATABLE READ READ UNCOMMITTED级别会导致数据完整性的严重问题,需要自己控制如何保持数据完整性 SERIALIZABLE会导致性能问题并增加死锁的机率 Mysql事务操作语句: 1. START TRANSACTION:开始事务,autocommit设为0,如果已经有一个事务在运行,则会触发一个隐藏的COMMIT 2. COMMIT:提交事务,保存更改,释放锁 3. ROLLBACK:回滚本事务对数据库的所有更改,然后结束事务,释放锁 4. SAVEPOINT savepoint_name:创建一个savepoint识别符来ROLLBACK TO SAVEPOINT 5. ROLLBACK TO SAVEPOINT savepoint_name:回滚到从savepoint_name开始对数据库的所有更改,这样就允许回滚事务中的一部分,保证更改的一个子集被提交 6. SET TRANSACTION:允许设置事务的隔离级别 7. LOCK TABLES:允许显式的锁住一个或多个table,会隐式的关闭当前打开的事务,建议在执行LOCK TABLES语句之前显式的commit或rollback。我们一般所以一般在事务代码里不会使用LOCK TABLES 定义事务 MySQL默认的行为是在每条SQL语句执行后执行一个COMMIT语句,从而有效的将每条语句独立为一个事务。 在复杂的应用场景下这种方式就不能满足需求了。 为了打开事务,允许在COMMIT和ROLLBACK之前多条语句被执行,我们需要做以下两步: 1, 设置MySQL的autocommit属性为0,默认为1 2,使用START TRANSACTION语句显式的打开一个事务 上面已经说了,当使用START TRANSACTION开始一个事物的时候,则SET autocommit=0不会起作用,因为START TRANSACTION会隐式的提交session中所有当前的更改,结束已有的事务,并打开一个新的事务。 使用SET AUTOCOMMIT语句的存储过程例子: sql代码 1. CREATE PROCEDURE tfer_funds 2. (from_account int, to_account int, tfer_amount numeric(10,2)) 3. BEGIN 4. SET autocommit=0; 5. 6. UPDATE account_balance SET balance=balance-tfer_amount WHERE account_id=from_account; 7. 8. UPDATE account_balance SET balance=balance+tfer_amount WHERE account_id=to_account; 9. 10. COMMIT; 11.END; 使用START TRANSACITON打开事务的例子: sql代码 1. CREATE PROCEDURE tfer_funds 2. (from_account int, to_account int, tfer_amount numeric(10,2)) 3. BEGIN 4. START TRANSACTION; 5. 6. UPDATE account_balance SET balance=balance-tfer_amount WHERE account_id=from_account; 7. 8. UPDATE account_balance SET balance=balance+tfer_amount WHERE account_id=to_account; 9. 10. COMMIT; 11.END; 通常COMMIT或ROLLBACK语句执行时才完成一个事务,但是有些DDL语句等会隐式触发COMMIT,所以应该在事务中尽可能少用或注意一下: Java代码 1. ALTER FUNCTION 2. ALTER PROCEDURE 3. ALTER TABLE 4. BEGIN 5. CREATE DATABASE 6. CREATE FUNCTION 7. CREATE INDEX 8. CREATE PROCEDURE 9. CREATE TABLE 10.DROP DATABASE 11.DROP FUNCTION 12.DROP INDEX 13.DROP PROCEDURE 14.DROP TABLE […]
View Details最近给客户做的一小系统是SQLSERVER的数据库,因为特殊原因要切换到MYSQL上去,切换数据库确实让人头疼的,SQLSERVER和MYSQL的存储过程还是有很大差别的,下面是我做切换时转换的MYSQL版的分页过程,和事务处理的一个测试过程,事务处理也不像SQLSERVER那样。不多说了,供学习MYSQL的兄弟们参考下,我用的MYSQL5.5版本,经过测试都是可行的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
<span style="color: #008080;">/*</span><span style="color: #008080;"> --名称:MYSQL版查询分页存储过程 by peace 2013-8-14 --输入参数:@fields -- 要查询的字段用逗号隔开 --输入参数:@tables -- 要查询的表 --输入参数:@where -- 查询条件 --输入参数:@orderby -- 排序字段 --输出参数:@page -- 当前页计数从1开始 --输出参数:@pagesize -- 每页大小 --输出参数:@totalcount -- 总记录数 --输出参数:@pagecount -- 总页数 </span><span style="color: #008080;">*/</span> <span style="color: #0000ff;">DROP</span> <span style="color: #0000ff;">PROCEDURE</span> <span style="color: #0000ff;">IF</span> <span style="color: #808080;">EXISTS</span> Query_Pagination; <span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">PROCEDURE</span> Query_Pagination ( <span style="color: #808080;">in</span> _fields <span style="color: #0000ff;">varchar</span>(<span style="font-weight: bold; color: #800000;">2000</span>), <span style="color: #808080;">in</span> _tables <span style="color: #0000ff;">text</span>, <span style="color: #808080;">in</span> _<span style="color: #0000ff;">where</span> <span style="color: #0000ff;">varchar</span>(<span style="font-weight: bold; color: #800000;">2000</span>), <span style="color: #808080;">in</span> _orderby <span style="color: #0000ff;">varchar</span>(<span style="font-weight: bold; color: #800000;">200</span>), <span style="color: #808080;">in</span> _pageindex <span style="color: #0000ff;">int</span>, <span style="color: #808080;">in</span> _pagesize <span style="color: #0000ff;">int</span>, <span style="color: #808080;">in</span> _sumfields <span style="color: #0000ff;">varchar</span>(<span style="font-weight: bold; color: #800000;">200</span>),<span style="color: #008080;">/*</span><span style="color: #008080;">增加统计字段2013-5-8 peaceli</span><span style="color: #008080;">*/</span> out _totalcount <span style="color: #0000ff;">int</span> , out _pagecount <span style="color: #0000ff;">int</span> ) <span style="color: #0000ff;">begin</span> <span style="color: #0000ff;">set</span> <span style="color: #008000;">@startRow</span> <span style="color: #808080;">=</span> _pageSize<span style="color: #808080;">*</span>(_pageIndex <span style="color: #808080;">-</span><span style="font-weight: bold; color: #800000;">1</span>); <span style="color: #0000ff;">set</span> <span style="color: #008000;">@pageSize</span> <span style="color: #808080;">=</span> _pageSize; <span style="color: #0000ff;">set</span> <span style="color: #008000;">@rowindex</span> <span style="color: #808080;">=</span> <span style="font-weight: bold; color: #800000;">0</span>; <span style="color: #0000ff;">set</span> <span style="color: #008000;">@strsql</span> <span style="color: #808080;">=</span> CONCAT(<span style="color: #ff0000;">'</span><span style="color: #ff0000;">select sql_calc_found_rows @rowindex:=@rowindex+1 as rownumber,</span><span style="color: #ff0000;">'</span>,_fields,<span style="color: #ff0000;">'</span><span style="color: #ff0000;"> from </span><span style="color: #ff0000;">'</span>,_tables,<span style="color: #ff00ff;">case</span> ifnull(_<span style="color: #0000ff;">where</span>,<span style="color: #ff0000;">''</span>) <span style="color: #0000ff;">when</span> <span style="color: #ff0000;">''</span> <span style="color: #0000ff;">then</span> <span style="color: #ff0000;">''</span> <span style="color: #0000ff;">else</span> concat(<span style="color: #ff0000;">'</span><span style="color: #ff0000;"> where </span><span style="color: #ff0000;">'</span>,_<span style="color: #0000ff;">where</span>) <span style="color: #0000ff;">end</span>,<span style="color: #ff0000;">'</span><span style="color: #ff0000;"> order by </span><span style="color: #ff0000;">'</span>,_orderby,<span style="color: #ff0000;">'</span><span style="color: #ff0000;"> limit </span><span style="color: #ff0000;">'</span>,<span style="color: #008000;">@startRow</span>,<span style="color: #ff0000;">'</span><span style="color: #ff0000;">,</span><span style="color: #ff0000;">'</span>,<span style="color: #008000;">@pageSize</span>); <span style="color: #0000ff;">prepare</span> strsql <span style="color: #0000ff;">from</span> <span style="color: #008000;">@strsql</span>; <span style="color: #0000ff;">execute</span> strsql; <span style="color: #0000ff;">deallocate</span> <span style="color: #0000ff;">prepare</span> strsql; <span style="color: #0000ff;">set</span> _totalcount <span style="color: #808080;">=</span> found_rows(); <span style="color: #0000ff;"> if</span> (_totalcount <span style="color: #808080;"><=</span> _pageSize) <span style="color: #0000ff;">then</span> |
1 2 3 4 5 6 7 |
<span style="color: #0000ff;">set</span> _pagecount <span style="color: #808080;">=</span> <span style="font-weight: bold; color: #800000;">1</span>; <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">if</span> (_totalcount <span style="color: #808080;">%</span> _pageSize <span style="color: #808080;">></span> <span style="font-weight: bold; color: #800000;">0</span>) <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">set</span> _pagecount <span style="color: #808080;">=</span> _totalcount <span style="color: #808080;">/</span> _pageSize <span style="color: #808080;">+</span> <span style="font-weight: bold; color: #800000;">1</span>; <span style="color: #0000ff;">else</span> <span style="color: #0000ff;">set</span> _pagecount <span style="color: #808080;">=</span> _totalcount <span style="color: #808080;">/</span> _pageSize; <span style="color: #0000ff;">end</span> <span style="color: #0000ff;">if</span>; <span style="color: #0000ff;">end</span> <span style="color: #0000ff;">if</span>; |
1 |
<span style="color: #0000ff;">if</span>(ifnull(_sumfields,<span style="color: #ff0000;">''</span>) <span style="color: #808080;"><></span> <span style="color: #ff0000;">''</span>) <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">set</span> <span style="color: #008000;">@sumsql</span> <span style="color: #808080;">=</span> contact(<span style="color: #ff0000;">'</span><span style="color: #ff0000;">select </span><span style="color: #ff0000;">'</span>,_sumfields,<span style="color: #ff0000;">'</span><span style="color: #ff0000;"> from </span><span style="color: #ff0000;">'</span>,_tables,<span style="color: #ff00ff;">case</span> ifnull(_<span style="color: #0000ff;">where</span>,<span style="color: #ff0000;">''</span>) <span style="color: #0000ff;">when</span> <span style="color: #ff0000;">''</span> <span style="color: #0000ff;">then</span> <span style="color: #ff0000;">''</span> <span style="color: #0000ff;">else</span> concat(<span style="color: #ff0000;">'</span><span style="color: #ff0000;"> where </span><span style="color: #ff0000;">'</span>,_<span style="color: #0000ff;">where</span>) <span style="color: #0000ff;">end</span>); <span style="color: #0000ff;">prepare</span> sumsql <span style="color: #0000ff;">from</span> <span style="color: #008000;">@sumsql</span>; <span style="color: #0000ff;">execute</span> sumsql; <span style="color: #0000ff;">deallocate</span> <span style="color: #0000ff;">prepare</span> sumsql; <span style="color: #0000ff;">end</span> <span style="color: #0000ff;">if</span>; <span style="color: #0000ff;">end</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">PROCEDURE</span> TransTest(<span style="color: #808080;">in</span> p1 <span style="color: #0000ff;">VARCHAR</span>(<span style="font-weight: bold; color: #800000;">20</span>),<span style="color: #808080;">in</span> p2 <span style="color: #0000ff;">VARCHAR</span>(<span style="font-weight: bold; color: #800000;">50</span>)) <span style="color: #0000ff;">BEGIN</span> <span style="color: #0000ff;">declare</span> err <span style="color: #0000ff;">int</span> <span style="color: #0000ff;">default</span> <span style="font-weight: bold; color: #800000;">0</span>; <span style="color: #008080;">/*</span><span style="color: #008080;">如果出现sql异常,则将err设置为1后继续执行后面的操作 </span><span style="color: #008080;">*/</span> <span style="color: #0000ff;">declare</span> <span style="color: #0000ff;">continue</span> handler <span style="color: #0000ff;">for</span> sqlexception <span style="color: #0000ff;">set</span> err<span style="color: #808080;">=</span><span style="font-weight: bold; color: #800000;">1</span>; <span style="color: #008080;">--</span><span style="color: #008080;"> 出错处理 </span> <span style="color: #0000ff;">set</span> autocommit <span style="color: #808080;">=</span> <span style="font-weight: bold; color: #800000;">0</span>; <span style="color: #0000ff;">insert</span> <span style="color: #0000ff;">into</span> sy_queryconfig(syq_id) <span style="color: #0000ff;">values</span>(p1); <span style="color: #0000ff;">insert</span> <span style="color: #0000ff;">into</span> sy_queryconfig(syq_id) <span style="color: #0000ff;">values</span>(p2); <span style="color: #0000ff;">if</span> err<span style="color: #808080;">=</span><span style="font-weight: bold; color: #800000;">1</span> <span style="color: #0000ff;">then</span> <span style="color: #0000ff;">ROLLBACK</span>; <span style="color: #0000ff;">ELSE</span> <span style="color: #0000ff;">COMMIT</span>; <span style="color: #0000ff;">end</span> <span style="color: #0000ff;">if</span>; <span style="color: #0000ff;">END</span> |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span style="color: #0000ff;">CREATE</span> <span style="color: #0000ff;">PROCEDURE</span> TransTest2(<span style="color: #808080;">in</span> p1 <span style="color: #0000ff;">VARCHAR</span>(<span style="font-weight: bold; color: #800000;">20</span>),<span style="color: #808080;">in</span> p2 <span style="color: #0000ff;">VARCHAR</span>(<span style="font-weight: bold; color: #800000;">50</span>)) <span style="color: #0000ff;">BEGIN</span> <span style="color: #008080;">/*</span><span style="color: #008080;">只要发生异常就回滚</span><span style="color: #008080;">*/</span> <span style="color: #0000ff;">declare</span> <span style="color: #0000ff;">exit</span> handler <span style="color: #0000ff;">for</span> sqlexception <span style="color: #0000ff;">BEGIN</span> <span style="color: #0000ff;">ROLLBACK</span>; <span style="color: #008080;">/*</span><span style="color: #008080;">返回异常处理结果等其它操作</span><span style="color: #008080;">*/</span> <span style="color: #0000ff;">END</span>; START <span style="color: #0000ff;">TRANSACTION</span>; <span style="color: #0000ff;">insert</span> <span style="color: #0000ff;">into</span> sy_queryconfig(syq_id) <span style="color: #0000ff;">values</span>(p1); <span style="color: #0000ff;">insert</span> <span style="color: #0000ff;">into</span> sy_queryconfig(syq_id) <span style="color: #0000ff;">values</span>(p2); <span style="color: #0000ff;">COMMIT</span>; <span style="color: #0000ff;">END</span> |
from:http://www.cnblogs.com/peaceli/archive/2013/08/14/MYSQL.html
View DetailsMariaDB 存储过程返回 汉字问题创建代码如下:CREATE DEFINER=root@localhost PROCEDURE test(IN id INT, OUT result VARCHAR(50))LANGUAGE SQLNOT DETERMINISTICCONTAINS SQLSQL SECURITY DEFINERCOMMENT "BEGIN if id = 1 then set result = '红字'; else set result = 'ghj'; end if;ENDset names utf8;set @a="; CALL test(0, @a);select @a;没有问题;set names utf8;set @a="; CALL test(1, @a);select @a;报错!运行总是无法成功返回汉字,郁闷——解决方案——————--create procedure t ( aa char(10) charset 'gbk') from:http://www.myexception.cn/mysql/744652.html
View Details经常在论坛看到问高CPU的问题,简单的总结一下。 1,首先你要确认,高CPU是不是是SQL SERVER进程引起的还是别的进程引起的,这个很容易,直接看任务管理器。 2,如果从任务管理器看出高CPU确实是用SQL SERVER引起的。 3,如果是SQL SERVER引起的。 3.1SQL SERVER的一个比较BAD的执行计划引起的,比如说缺少必要的INDEX,引起了hash join什么的。这个也分成2种: 1,造成高CPU的语句已经执行结束,这个时候可以用下面的语句来检查。 select highest_cpu_queries.plan_handle, highest_cpu_queries.total_worker_time, q.dbid, q.objectid, q.number, q.encrypted, q.[text] from (select top 50 qs.plan_handle, qs.total_worker_time from sys.dm_exec_query_stats qs order by qs.total_worker_time desc) as highest_cpu_queries cross apply sys.dm_exec_sql_text(plan_handle) as q order by highest_cpu_queries.total_worker_time desc 解释一下sys.dm_exec_query_stats: sys.dm_exec_query_stats返回缓存查询计划的聚合性能统计信息。每个查询计划在该视图中对应一行,并且行的生存期与计划本身相关联。在从缓存删除计划时,也将从该视图中删除对应行。 可查看帮助文档:ms-help://MS.SQLCC.v9/MS.SQLSVR.v9.zh-CHS/tsqlref9/html/eb7b58b8-3508-4114-97c2-d877bcb12964.htm 3.1.2,造成高CPU的语句正在运行,这个时候可以用下面的语句来检查。 SELECT st.text, qp.query_plan, rq.* FROM sys.dm_exec_requests RQ CROSS APPLY sys.dm_exec_sql_text(rq.sql_handle) as st CROSS APPLY sys.dm_exec_query_plan(rq.plan_handle) as qp order by RQ.CPU_time desc 3.2 开启了SQL profiler. 通过3.1.2可以看到 sp_trace_getdata这个SP在运行。 […]
View Details— 查看性能记数器 SELECT * FROM sys.dm_os_performance_counters — 执行过的线程所遇到的所有等待(不是当前正在运行的线程, 为自上次重置统计信息或启动服务器以来累积的数据),可分析靠前的几个等待较高的事件。 select * from sys.dm_os_wait_stats order by wait_time_ms desc 该动态视图的细节,请查看帮助文档. — 重置该动态视图 DBCC SQLPERF ('sys.dm_os_wait_stats', CLEAR); GO — 正在等待某些资源的任务的等待队列 select * from sys.dm_os_waiting_tasks order by wait_duration_ms desc 内存使用: 查看当前由 SQL Server 分配的内存对象(KB): select sum((page_size_in_bytes/1024)*max_pages_allocated_count) from sys.dm_os_memory_objects; 查看系统内存当前信息: select * from sys.dm_os_sys_memory (这个动态视图只在sql 2008中才有) select cpu_count, hyperthread_ratio, scheduler_count, physical_memory_in_bytes / 1024 / 1024 […]
View Details--前10名其他等待类型 SELECT TOP 10 * from sys.dm_os_wait_stats ORDER BY wait_time_ms DESC SELECT *FROM sys.dm_os_wait_stats WHERE wait_type like 'PAGELATCH%' OR wait_type like 'LAZYWRITER_SLEEP%' --CPU的压力 SELECT scheduler_id, current_tasks_count, runnable_tasks_count FROM sys.dm_os_schedulers WHERE scheduler_id < 255 --表现最差的前10名使用查询 SELECT TOP 10 ProcedureName = t.text, ExecutionCount = s.execution_count, AvgExecutionTime = isnull ( s.total_elapsed_time / s.execution_count, 0 ), AvgWorkerTime = s.total_worker_time / s.execution_count, TotalWorkerTime = s.total_worker_time, MaxLogicalReads = s.max_logical_reads, MaxPhysicalReads = s.max_physical_reads, MaxLogicalWrites = s.max_logical_writes, CreationDateTime = s.creation_time, CallsPerSecond = isnull ( s.execution_count / datediff ( second , s.creation_time, getdate ()), 0 ) FROM […]
View Details我的俄罗斯名叫作“不折腾不舒服斯基”,所以,不将分区表好好折腾一下,我就是不舒服。 在前面,我们介绍过怎么样直接创建一个分区表,也介绍过怎么将一个普通表转换成一个分区表。那么,这两种方式创建的表有什么区别呢?现在,我又最新地创建了两个表: 第一个表名为Sale,这个表使用的是《SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表?》中的方法创建的,在创建完之后,还为该表添加了一个主键。 第二个表名Sale1,这个表使用的是《SQL Server 2005中的分区表(三):将普通表转换成分区表 》中的方法创建的,也就是先创建了一个普通表,然后通过为普通表添加聚集索引的方式将普通表转换成已分区表的方式。 通过以上方法都可以得到一个已分区表,但是,这两个已分区表还是有点区别的,区别在哪里呢?我们分别查看一下这两个表的索引和主键吧,如下图所示。 从上图可以看出,直接创建的分区表Sale的索引里,只有一个名为PK_Sale的索引,这个索引是唯一的、非聚集的索引,也就是在创建PK_Sale主键时SQL Server自动创建的索引。而经普通表转换成分区表的Sale1的索引里,除了在创建主键时由SQL Server自动创建的名为PK_Sale1的唯一的、非聚集的索引之外,还存在一个名为CT_Sale1的聚集索引。 对于表Sale来说,可以通过修改分区函数的方式来将其转换成普通表,具体的修改方式请看《SQL Server 2005中的分区表(四):删除(合并)一个分区》,事实上,就是将分区函数中的所有分区分界都删除,那么,这个分区表中的所有数据就只能存在第一个分区表中了。在本例中,可以使用以下代码来修改分区函数。 [c-sharp] view plaincopy ALTER PARTITION FUNCTION partfunSale() MERGE RANGE ('20100101') ALTER PARTITION FUNCTION partfunSale() MERGE RANGE ('20110101') ALTER PARTITION FUNCTION partfunSale() MERGE RANGE ('20120101') ALTER PARTITION FUNCTION partfunSale() MERGE RANGE ('20130101') 事实上,这么操作之后,表Sale还是一个分区表,如下图所示,只不过是只有一个分区的分区了,这和普遍表就没有什么区别了。 对于通过创建分区索引的方法将普通表转换成的分区表而言,除了上面的方法之外,还可以通过删除分区索引的办法来将分区表转换成普通表。但必须要经过以下两个步骤: 1、删除分区索引 2、在原来的索引字段上重建一个索引。 先说删除分区索引吧,这一步很简单,你可以直接在SQL Server Management Studio上将分区索引删除,也可以使用SQL语句删除,如本例中可以使用以下代码删除已经创建的分区索引。 [c-sharp] view plaincopy drop index Sale1.CT_Sale1 一开始,我还以为只要删除了分区索引,那么分区表就会自动转换成普通表了,可是在删除索引之后,查看一下该表的属性,结果还是已分区表,如下图所示。 不但如此,而且,还不能将原来的聚集的唯一索引(在本例中为主键的那个索引)改成聚集索引,如下图所示。 如果要彻底解决这个问题,还必须要在原来创建分区索引的字段上重新创建一下索引,只有重新创建过索引之后,SQL Server才能将已分区表转换成普通表。在本例中可以使用以下代码重新创建索引。 [c-sharp] view plaincopy CREATE CLUSTERED INDEX CT_Sale1 ON Sale1([SaleTime]) ON [PRIMARY] Go 重建索引之后,分区表就变成了普通表,现在再查看一下Sale1表的属性,我们可以看到原来的分区表已经变成了普通表,如下图所示。 当然,以上两个步骤也可以合成一步完成,也就是在重建索引的同时,将原索引删除。如以下代码所示: [c-sharp] view plaincopy CREATE CLUSTERED INDEX CT_Sale1 ON Sale1([SaleTime]) WITH ( DROP_EXISTING = ON) ON [PRIMARY] 按理说,在SQL Server Management Studio中的操作和使用SQL语句的操作是一样的,可是我在SQL Server Management Studio中将聚集索引删除后再在该字段上重新创建一个同名的索引,并重新生成和组织该索引,可是分区表还是没有变成普通表,这就让我百思不得其解了。不过呢,只要能用SQL语句达到目的,那我们就用它吧。 原创不容易,转载请注明出处。http://blog.csdn.net/smallfools/archive/2009/12/14/5004100.aspx
View Details所谓天下大事,分久必合,合久必分,对于分区表而言也一样。前面我们介绍过如何删除(合并)分区表中的一个分区,下面我们介绍一下如何为分区表添加一个分区。 为分区表添加一个分区,这种情况是时常会 发生的。比如,最初在数据库设计时,只预计了存放3年的数据,可是到了第4天怎么办?这样的话,我们就可以为分区表添加一个分区,让它把新的数据放在新的分区里。再比如,最初设计时,一个分区用于存放一年的数据,结果在使用的时候才发现,一年的数据太多,想将一个分区中的数据分为两个分区来存放。 遇到这种情况,就必须要为分区表添加一个分区了。 当然,我们也可以使用修改分区函数的方式来添加一个分区,但是在修改分区函数时,我们必须要注意另一个问题——分区方案。为什么还要注意分区方案呢?我们回过头来看一下前面是怎么定义分区函数和分区方案的,如以下代码所示: [c-sharp] view plaincopy --添加分区函数 CREATE PARTITION FUNCTION partfunSale (datetime) AS RANGE RIGHT FOR VALUES ('20100101′,’20110101′,’20120101′,’20130101') --添加分区方案 CREATE PARTITION SCHEME partschSale AS PARTITION partfunSale TO ( Sale2009, Sale2010, Sale2011, Sale2012, Sale2013) 从以上代码中可以看出,分区函数定义了用于分区的数据边界,而分区函数指定了符合分区边界的数据存放在文件组。因此,分区方案中指定的文件组个数应该是比分区函数中指定的边界数大1的。如上例中,分区函数中指定的边界数为4,那么在分区方案中指定的文件组数就为5。 如果,我们将分区函数中的边界数增加一个,那么分区方案中的文件组数也就要相应地增加一个。因此,我们不能简简单单地通过修改分区函数的方式来为分区表添加一个分区。 那么,我们应该怎么做呢?是不是要先为分区方案添加一个文件组? 这种想法是没有错的,想要为分区表添加一个分区,可以通过以下两个步骤来实现: 1、为分区方案指定一个可以使用的文件组。 2、修改分区函数。 在为分区方案指定一个可用的文件组时,该分区方案并没有立刻使用这个文件组,只是将文件组先备用着,等修改了分区函数之后分区方案才会使用这个文件组(不要忘记了,如果分区函数没有变,分区方案中的文件组个数就不能变)。 为分区方案指定一个可用的文件组的代码如下所示: [c-sharp] view plaincopy ALTER PARTITION SCHEME partschSale NEXT USED [Sale2010] 其中: 1、ALTER PARTITION SCHEME意思是修改分区方案 2、partschSale是分区方案名 3、NEXT USED意思是下一个可使用的文件组 4、[Sale2010]是文件组名 为分区方案添加了下一个可使用的文件组之后,分区方案并没有立刻使用这个文件组,此时我们可以通过查看分区方案的源代码来证实。查看方法是:在SQL Server Management Studio中,选择数据库-->存储-->分区方案,右击分区方案名,在弹出的菜单中选择“编写分区方案脚本为”-->CREATE到-->新查询编辑器窗口,如下图所示: 为分区方案添加了下一个可使用的文件组之后,我们就可以动手修改分区函数了,使用代码如下所示: [c-sharp] view plaincopy ALTER PARTITION FUNCTION partfunSale() SPLIT RANGE ('20100101') 其中: 1、ALTER PARTITION FUNCTION意思是修改分区函数 2、partfunSale()为分区函数名 3、SPLIT RANGE 意思是分割界限 4、’20100101′ 是用于分割的界限值 当然,我们在修改分区函数前后都可以统计一下各物理分区的数据记录情况,如以下代码所示: [c-sharp] view plaincopy --统计所有分区表中的记录总数 select $PARTITION.partfunSale(SaleTime) as 分区编号,count(id) as 记录数 from Sale group by $PARTITION.partfunSale(SaleTime) --原来的分区函数是将2010-1-1之前的数据放在第1个分区表中,将2010-1-1至2011-1-1之间的数据放在第2个分区表中 --现在需要将2011-1-1之前的数据都放在第1个分区表中,也就是将第1个分区表和第2个分区表中的数据合并 --修改分区函数 ALTER PARTITION FUNCTION partfunSale() SPLIT RANGE ('20100101') --统计所有分区表中的记录总数 select $PARTITION.partfunSale(SaleTime) as 分区编号,count(id) as 记录数 from Sale group by $PARTITION.partfunSale(SaleTime) 以上代码的运行结果如下图所示: 从上图中可以看出,分区表中已经添加了一个分区,我们也可以再一次查看分区方案的源代码,如下图所示,这个时候分区方案也自动添加了一个文件组。 原创不容易,转载请注明出处。http://blog.csdn.net/smallfools/archive/2009/12/04/4940185.aspx
View Details在前面我们介绍过如何创建和使用一个分区表,并举了一个例子,将不 同年份的数据放在不同的物理分区表里。具体的分区方式为: 第1个小表:2010-1-1以前的数据(不包含2010-1-1)。 第2个小表:2010-1-1(包含2010-1-1)到2010-12-31之间的数据。 第3个小表:2011-1-1(包含2011-1-1)到2011-12-31之间的数据。 第4个小表:2012-1-1(包含2012-1-1)到2012-12-31之间的数据。 第5个小表:2013-1-1(包含2013-1-1)之后的数据。 分区函数的代码如下所示: [c-sharp] view plaincopy CREATE PARTITION FUNCTION partfunSale (datetime) AS RANGE RIGHT FOR VALUES ('20100101′,’20110101′,’20120101′,’20130101') 假设我们在创建分区表之后发现,2010年以前的数据并不多,完全可以将它们与2010年的数据进行合并,放在同一个分区里,也就是说,具体的分区方式改为: 第1个小表:2011-1-1以前的数据(不包含2011-1-1)。 第2个小表:2011-1-1(包含2011-1-1)到2011-12-31之间的数据。 第3个小表:2012-1-1(包含2012-1-1)到2012-12-31之间的数据。 第4个小表:2013-1-1(包含2013-1-1)之后的数据。 由于上面的需求更改了数据分区的条件,因此,我们必须要修改分区函数,因为分区函数的作用就是要来告诉SQL Server怎么存放数据的。只要分区函数修改了,SQL Server会自动将数据重新分配,按照新的分区函数指定的方式来存储数据。 先假设我们还没有创建过分区表,要满足上面的条件,我们必须要写出如下代码的创建分区函数的SQL语句 [c-sharp] view plaincopy CREATE PARTITION FUNCTION partfunSale (datetime) AS RANGE RIGHT FOR VALUES ('20110101′,’20120101′,’20130101') 比较一个新的分区函数和老的分区函数,看看他们有什么区别? 的确,我们很容易就可以发现,老的分区函数里多了一个分界值——也就是’20100101’。那么,修改老的分区函数,事实上就是将这分界值删除。简单一点说,删除(合并)一个分区,事实上就是在分区函数中将多余的分界值删除。 删除分区函数中的分界值,也就是修改分区函数的方法如下所示: [c-sharp] view plaincopy ALTER PARTITION FUNCTION partfunSale() MERGE RANGE ('20100101') 其中: 1、ALTER PARTITION FUNCTION 意思是修改分区函数 2、partfunSale()为分区函数名 3、MERGE RANGE意思是合并界限。事实上,合并界限和删除分界值是一个意思。 我们可以在修改分区函数时先统计一下各物理分区中的记录总数,在修改分区之后,再统计一下各物理分区中的记录总数,看一下修改分区函数后的数据变化情况,代码如下所示: [c-sharp] view plaincopy --统计所有分区表中的记录总数 select $PARTITION.partfunSale(SaleTime) as 分区编号,count(id) as 记录数 from Sale group by $PARTITION.partfunSale(SaleTime) --原来的分区函数是将2010-1-1之前的数据放在第1个分区表中,将2010-1-1至2011-1-1之间的数据放在第2个分区表中 --现在需要将2011-1-1之前的数据都放在第1个分区表中,也就是将第1个分区表和第2个分区表中的数据合并 --修改分区函数 ALTER PARTITION FUNCTION partfunSale() MERGE RANGE ('20100101') --统计所有分区表中的记录总数 select $PARTITION.partfunSale(SaleTime) as 分区编号,count(id) as 记录数 from Sale group by $PARTITION.partfunSale(SaleTime) 运行结果如下图所示: 现在还有一个问题,就是通过修改分区函数合并数据之后,数据都存放在哪里了?在修改之前,数据分别存放在文件组Sale2009和Sale2010中,修改之后,数据放到哪里去了呢? 事实上,在修改分区函数之后,SQL Server也会自动修改分区方案,将处于两个物理分区中的数据放在同一个物理分区里了。可以通过查看分区方案的方式来查看数据具体的存放位置。 查看分区方案的方式为:在SQL Server Management Studio中,选择数据库-->存储-->分区方案,右击分区方案名,在弹出的菜单中选择“编写分区方案脚本为”-->CREATE到-->新查询编辑器窗口 然后在新查询编辑器窗口可以看到下图代码。 从上图中可以看出,分区方案将原来Sale2010文件组中的数据合并到了Sale2009文件组中。 原创不容易,转载请注明出处。http://blog.csdn.net/smallfools/archive/2009/12/04/4937878.aspx
View Details在设计数据库时,经常没有考虑到表分区的问题,往往在数据表承重的负担越来越重时,才会考虑到分区方式,这时,就涉及到如何将普通表转换成分区表的问题了。 那么,如何将一个普通表转换成一个分区表 呢?说到底,只要将该表创建一个聚集索引,并在聚集索引上使用分区方案即可。 不过,这回说起来简单,做起来就复杂了一点。还是接着上面的例子,我们先使用以下SQL语句将原有的Sale表删除。 [c-sharp] view plaincopy --删除原来的数据表 drop table Sale 然后使用以下SQL语句创建一个新的普通表,并在这个表里插入一些数据。 [c-sharp] view plaincopy --新建一个普通的数据表 CREATE TABLE Sale( [Id] [int] IDENTITY(1,1) NOT NULL, --自动增长 [Name] [varchar](16) NOT NULL, [SaleTime] [datetime] NOT NULL, CONSTRAINT [PK_Sale] PRIMARY KEY CLUSTERED --创建主键 ( [Id] ASC ) ) --插入一些记录 insert Sale ([Name],[SaleTime]) values ('张三',’2009-1-1′) insert Sale ([Name],[SaleTime]) values ('李四',’2009-2-1′) insert Sale ([Name],[SaleTime]) values ('王五',’2009-3-1′) insert Sale ([Name],[SaleTime]) values ('钱六',’2010-4-1′) insert Sale ([Name],[SaleTime]) values ('赵七',’2010-5-1′) insert Sale ([Name],[SaleTime]) values ('张三',’2011-6-1′) insert Sale ([Name],[SaleTime]) values ('李四',’2011-7-1′) insert Sale ([Name],[SaleTime]) values ('王五',’2011-8-1′) insert Sale ([Name],[SaleTime]) values ('钱六',’2012-9-1′) insert Sale ([Name],[SaleTime]) values ('赵七',’2012-10-1′) insert Sale ([Name],[SaleTime]) values ('张三',’2012-11-1′) insert Sale ([Name],[SaleTime]) values ('李四',’2013-12-1′) insert Sale ([Name],[SaleTime]) values ('王五',’2014-12-1′) 使用以上代码创建的表是普通表,我们来看一下表的属性,如下图所示。 在以上代码中,我们可以看出,这个表拥有一般普通表的特性——有主键,同时这个主键还是聚集索引。前面说过,分区表是以某个字段为分区条件,所以,除了这个字段以外的其他字段,是不能创建聚集索引的。因此,要想将普通表转换成分区表,就必须要先删除聚集索引,然后再创建一个新的聚集索引,在该聚集索引中使用分区方案。 可惜的是,在SQL Server中,如果一个字段既是主键又是聚集索引时,并不能仅仅删除聚集索引。因此,我们只能将整个主键删除,然后重新创建一个主键,只是在创建主键时,不将其设为聚集索引,如以下代码所示: [c-sharp] view plaincopy --删掉主键 ALTER TABLE Sale DROP constraint PK_Sale --创建主键,但不设为聚集索引 ALTER TABLE Sale ADD CONSTRAINT PK_Sale PRIMARY KEY NONCLUSTERED ( [ID] ASC ) ON [PRIMARY] 在重新非聚集主键之后,就可以为表创建一个新的聚集索引,并且在这个聚集索引中使用分区方案,如以下代码所示: [c-sharp] view plaincopy --创建一个新的聚集索引,在该聚集索引中使用分区方案 CREATE CLUSTERED INDEX CT_Sale ON Sale([SaleTime]) ON partschSale([SaleTime]) 为表创建了一个使用分区方案的聚集索引之后,该表就变成了一个分区表,查看其属性,如下图所示。 我们可以再一次使用以下代码来看看每个分区表中的记录数。 [c-sharp] view plaincopy --统计所有分区表中的记录总数 select $PARTITION.partfunSale(SaleTime) as 分区编号,count(id) as 记录数 from Sale group by $PARTITION.partfunSale(SaleTime) 以上代码的运行结果如下所示,说明在将普通表转换成分区表之后,数据不但没有丢失,而且还自动地放在了它应在的分区表中了。 原创不容易,转载请注明出处。http://blog.csdn.net/smallfools/archive/2009/12/03/4934119.aspx
View Details