那些年我们写过的T-SQL(下篇)(转)
原文:http://www.cnblogs.com/wanliwang01/p/TSQL_Base04.html
下篇的内容很多都会在工作中用到,尤其是可编程对象,那些年我们写过的存储过程,有木有?到目前为止很多大型传统企业仍然很依赖存储过程。这部分主要难理解的部分是事务和锁机制这块,本文会进行简单的阐述。虽然很多SQL命令可以通过工具自动生成,但如果能通过记忆的话速度会更快,那么留给自己思考的时间就越多。此外,由于锁这部分知识比较复杂,不同的数据库厂商的实现也有不同,SQLSERVER除了我们常见的共享锁、排它锁(包括表级、页级、行级),意向锁,还有一些更复杂的锁,如自旋锁等,这部分内容会在之后的T-SQL深入解析部分再做介绍。言归正传,让我们回到T-SQL的世界咯,希望一天我能成为这个世界里的一只小小的功夫熊猫,写起SQL来,下笔如有神。
熊二恭祝大家猴年猴赛雷!
此外,刚仔细学习了下汤雪华大神关于12306领域模型设计的文章,对于思路是一种很好的启迪,推荐下http://www.cnblogs.com/netfocus/p/5187241.html,博主xuanbg在评论中提及的动态分裂的思路也是棒棒哒。
本节主要介绍常见的DML操作,一般的添删改查INSERT、UPDATE、DELETE(TRUNCATE),以及特殊一点的MERGE。其中T-SQL支持一下五种类型的INSERT,如下所示。
语句类型 |
解释与示例 |
INSERT VALUES |
标准方式:INSERT INTO dbo.Orders(orderid, orderdate, empid, custid) VALUES(10001, '20160207', 3, 'A') |
INSERT SELECT |
使用便捷:INSERT INTO dbo.Orders(orderid, orderdate, empid, custid) SELECT 10001, '20120207', 2, 'B' UNION ALL SELECT 10002, '20120207', 3, 'C' |
INSERT EXEC |
INSERT INTO dbo.Orders(orderid, orderdate, empid, custid) EXEC Sales.GetOrder @country = 'China' |
SELECT INTO |
SELECT courtry, region, city INTO dbo.locations FROM Sales.Customers EXCEPT SELECT courtry, region, city FROM HR.Employees |
BULK INSERT |
类似SSIS的导入功能 BULK INSERT dbo.Orders FROM 'C;\orders.txt' WITH (DATAFILETYPE = 'char', FIELDTERMINATOR = ',', ROWTERMINATOR = '\n' ) |
接下来,介绍IDENTITY标识列的相关知识,以及T-SQL对sequence的支持,和ORACLE中序列一致。需要注意的是标识值无论操作是否成功都会自动增长,因此当需要真心连续的记录号时,需要自己的替代方案。新增的序列对象是标准的SQL功能,它与标识列属性不同,是一个不会绑定到特定表中列的对象,需要时查询获取即可。
操作类型 |
解释与示例 |
创建标识列 |
CREATE TABLE dbo.T1 (keycol INT NOT NULL IDENTITY(1, 1) CONSTRAINT PK_T1 PRIMARY KEY) |
插入数据(有标识列的情况下) |
注意忽略标识列,INSERT INTO dbo.T1(datacol) VALUES('AAAAA') |
获取当前标识号 |
SELECT SCOPE_IDENTITY(), @@identity, IDENT_CURRENT('Sales.Orders') 第一列获取当前作用域下的标识号,第二列获取会话生成的最后一个标识号(无论作用域),最后一个获取全局的标记号,与会话无关 |
显示插入标识 |
SET IDENTITY_INSERT表名 ON/OFF |
创建序列 |
CREATE SEQUENCE dbo.SeqOrderIDS AS INT MIN VALUE 1 CYCLE; |
使用序列 |
SELECT NEXT VALUE FOR dbo.SeqOrderIDS |
- 删除和更新操作
操作类型 |
解释与示例 |
一般删除 |
DELETE FROM dbo.Orders WHERE orderdate < '20160207' |
TRANCATE语句 |
TRANCATE TABLE dbo.T1,测试时经常使用,更高效,其实相当于先删除表再创建表,而不是delete那样按条删除。DELETE是用完全日志模式,TRANCATE使用最小日志模式 |
基于联接的DELETE |
场景:从Orders表中删除所有与Customers表中美国客户相关的行 标准方式:DELETE FROM dbo.Orders WHERE EXISTS ( SELECT * FROM dbo.Customer AS WHERE Orders.Custid = C.Custid AND C.Country = 'USA') 联接DELETE:DELETE FROM O FROM dbo.Orders AS O JOIN dbo.Customers AS C ON O.custid = C.custid WHERE C.country = 'China' |
一般更新 |
UPDATE dbo.OrderDetails SET discount = discount + 0.05 WHERE productid = 50 |
基于联接的UPDATE |
场景:对客户1的所有订单明细增加5%折扣 标准方式:UPDATE dbo.OrderDetails SET discount += 0.05 WHERE EXISTS( SELECT * FROM dbo.Orders AS O WHERE O.orderid = OrderDetails.orderid AND O.custid = 1) 联接UPDATE:UPDATE OD SET discount += 0.05 FROM dbo.OrderDetails AS OD JOIN dbo.Orders AS O ON OD.orderid = O.orderid WHERE O.custid =1 |
赋值UPDATE |
DECLARE @nextval AS INT; UPDATE dbo.Sequences SET @nextval = val+= 1 WHERE id = 'SEQ1' |
- 合并数据和OUTPUT字句
从2008版本开始,T-SQL新增了一个MERGE操作符,相当于其他DML操作的组合,此外为了减少查询次数,可以通过OUTPUT字句将更新的操作输出(类似于触发器的功能,包含inserted、deleted隐藏表),便于构建相应的流水表,不过实话实说通过业务来执行流水操作,比SQL组合更加合理,继续使用表格将相关应用表述出来。
操作类型 |
解释与示例 |
合并数据MERGE |
MERGE INTO dbo.Customers AS TGT USING dbo.CustomerStage AS SRC ON TGT.custid = SRC.custid WHEN MATCHED THEN UPDATE SET TGT.company = SRC.companyname, TGT.phone = SRC.phone, TGT.address = SRC.address WHEN NOT MATCHED THEN INSERT (custid, companyname, phone, address) VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address) |
通过表表达式修改数据 |
WITH C AS( SELECT custid, OD.orderid, productid, discount, discount + 0.05 AS newdiscount FROM dbo.OrderDetails AS OD JOIN dbo.Orders AS O ON OD.orderid = O.orderid WHERE O.custid = 1 ) UPDATE C SET discount = newdiscount 补充一点是,内部的查询操作支持TOP关键字哦 |
OUTPUT字句 |
场景:从Orders表中删除所有与Customers表中美国客户相关的行 标准方式:DELETE FROM dbo.Orders WHERE EXISTS ( SELECT * FROM dbo.Customer AS WHERE Orders.Custid = C.Custid AND C.Country = 'USA') 联接DELETE:DELETE FROM O FROM dbo.Orders AS O JOIN dbo.Customers AS C ON O.custid = C.custid WHERE C.country = 'China' |
INSERT OUTPUT |
INSERT INTO dbo.T1(datacol) OUTPUT inserted.keycol, inserted.datacol SELECT lastname FROM HR.Employees WHERE country = 'China' 其中datacol是需要返回的属性 |
DELETE OUTPUT |
DELETE FROM dbo.Orders OUTPUT deleted.orderid, deleted.orderid, deleted.empid, deleted.custid WHERE orderdate < '20160101' |
UPDATE OUTPUT |
UPDATE dbo.OrderDetails SET discount += 0.05 OUTPUT inserted.productid, deleted.discount AS olddiscount, inserted.discount AS newdiscount WHERE productid = 51 |
事务的概念早已为大家所熟知,想提的一点是其也可以称之为工作单元,包含查询和修改数据的多种活动,UnitOfWork工作单元这个企业架构设计模式实际上也是其实现之一。实际中,最常见的是将插入订单和插入订单详细放入一个事务中,事务的ACID属性及简单事务应用示例如下。
原子性(Atom): 事务是一个原子的工作单元,一起提交或撤销。
一致性(Consistency): 其是一个主观概念,取决于应用程序的需求,指数据的状态,与之后数据库的隔离级别紧密关联。
隔离性(Isolation): 其实一种控制访问数据的机制,在T-SQL中,支持锁和行版本控制两种模式来处理隔离。
持久性(Duration): 数据修改在写入数据文件前,会先写入日志文件,但出现故障时,会通过重做和撤销来恢复数据。
DECLARE @neworderid AS INT INSERT INTO Sales.Order(custid, orderdate) VALUES (34, '20160213') SET @neworderid = SCOPE_IDENTITY() INSERT INTO Sales.OrderDetail(ordered, productid, unitprice, qty, discount) VALUES (@@orderid, 11, 14.00, 12, 0.000) |
- 锁和阻塞
正如之前所提到的T-SQL支持两种模式来处理隔离,一种是锁,这是一种"悲观式并发",在默认的READ COMMITED隔离级别下,一旦一个事务中修改数据,那么这个将不能被其他事务读取,因为会给该数据加上排它锁,而当读取数据时获取共享锁,其他事务可以并行读取;另一种是行版本控制技术,是一种"乐观式并发",其默认的隔离级别为READ COMMITED SNAPSHOT,事务中修改数据时,其他事务时可以进行读取操作的。
接下来介绍数据库中可以锁定的资源,包括行、页、表(对象)、数据库,按序锁定的资源粒度越来越大。行驻留在页中,而是包含表或索引数据的物理数据块。更复杂的可锁定资源包括范围、分配单元、堆&B树等,这儿暂不深究。在SQL SERVER中,如果要获得某个资源类型的锁,首先要获得起对应更高粒度级别上的意向锁,例如获得一个行上排他锁,那么该事务需要获取行所在页的意向排它锁和一个拥有该页对象的意向排它锁,意向锁的目的在于便于在更高粒度级别有效检测不相容的锁请求,用一个简单的表格来描述锁模式情况下锁的兼容性。
请求的锁模式 |
授予了排它锁(X) |
授予了共享锁(S) |
授予了意向排它锁(IX) |
授予了意向共享锁(IS) |
能否授予请求排它锁 |
No |
No |
No |
No |
能否授予请求共享锁 |
No |
Yes |
No |
Yes |
能否授予意向排它锁 |
No |
No |
Yes |
Yes |
能否授予意向排它锁 |
No |
Yes |
Yes |
Yes |
看到这儿不禁要问,为什么不都使用最小粒度的锁,这样的并发性不是更好么?实际上锁是需要消耗资源的,因此需要在时间和空间上折衷。在默认情况下,系统首先获取细粒度的锁,并在某些情况下,触发锁升级,例如一条语句中获取5000个行锁,那么将升级为页锁。此外,T-SQL支持ALTER TABLE语句设置LOCK_ESCALATION控制锁升级行为,包括是否支持锁升级和发生升级时的粒度(如页升级为表或分区)。
一般情况下,阻塞的出现是正常的,比如一个读操作等待排他锁的释放,但有时阻塞时间过长,严重影响响应时需要排除阻塞。可以通过如下几种查询动态视图的方式来查看系统中当前的阻塞并排除相关阻塞。
操作类型 |
解释与示例 |
查询会话相关锁信息 |
SELECT request_session_id AS spid, resource_type AS restype, resource_database_id AS dbid, DB_NAME(resource_database_id) AS dbname, resource_description AS res, resource_associated_entity_id AS resid, request_mode AS mode, request_status AS status FROM sys.dm_tran_locks 其中spid表示进程ID,restype表示锁定的资源类型(KEY, PAGE, Database, object),mode表示锁模式,status表示是否授予了锁 |
查询连接相关信息 |
SELECT session_id AS spid, connect_time, last_read, last_write, most_recent_sql_handle FROM sys.dm_exec_connections WHERE session_id IN (60, 61) 其中connect_time表示连接时间,write&read_time表示读写时间,most_recent_sql_handle表示该连接中最近的批处理语句的句柄。接下来可以通过一个简单的APPLY表运算符获取相应的SQL语句 SELECT session_id AS spid, text FROM sys.dm_exec_connections CROSS APPLY sys.dm_exec_sql_text(most_recent_sql_handle) AS st WHERE session_id IN (60, 61) |
查询会话相关信息 |
SELECT session_id as spid, login_time, host_name, program_name ,login_name, nt_user_name, last_request_start_time, last_request_end_time FROM sys.dm_exec_sessions WHERE session_id in (60, 61) 其中包括会话的登陆时间、主机名、程序名、登录名、WindowsNT用户名,最后的请求开始和结束时间等信息 |
查询请求相关信息 |
SELECT session_id AS spid, blocking_session_id, command, sql_handle, database_id, wait_type, wait_time, wait_resource FROM sys.dm_exec_requests WHERE blocking_session_id > 0 其中包括阻塞该会话的某个会话ID、阻塞的毫秒数等,可以通过blocking_session_id > 0判断是否为阻塞会话 |
处理阻塞 |
可以通过kill <spid>方式关闭会话,此外还可以设置会话中锁的时间,包括0立即超时,-1无超时(默认值),和n>0超时毫秒数 |
- 隔离级别
数据库的隔离级别决定了并发用户读取和写入的行为,一般来说隔离级别越高,数据的一致性越好,并发性越弱,接下来首先锁机制下的隔离级别。
READ UNCOMMITED: 最低的隔离级别,读取时不需要请求共享锁,会出现脏读,在对数据一致性要求不高的情况下使用,在实际中通过WITH NOLOCK方式使用。
READ COMMITED: 系统默认的隔离级别,支持读取已提交的数据,通过要求读取者获取共享锁来防止未提交的读取,但由于其会在读取完成后释放锁,因而会存在在两次读取之间数据不一致的问题(也称之为不可重复读)。
REPEATABLE READ: 可重复读通过在事务中始终持有读共享锁的方式防止两次不同的读取。同时由于在该隔离级别下,共享锁会一直持有,因而无法获取排它锁,也防止了丢失更新的情况,比如在低级别的隔离级别下,两个事务中均修改某个值,那么后面一个修改会奏效。
SERIALIZABLE: 最高的隔离级别,其除了在读请求时一直持有读共享锁,同时还会限定查询筛选所限的key键的范围(之间提及的锁范围),用于阻止其他事务尝试添加新行(被限定情况下),防止了出现幻读的情况。
接下来,介绍行版本模式(该模式通过tempdb存储已提交行的之前版本,之后的深入剖析文章中还会重点介绍tempdb)下的隔离级别,,包括SNAPSHOT和READ COMMITTED SNAPSHOT,分别对应锁模式下的SERIALIZABLE和READ COMMITTED,区别是行版本模式下不会发出读共享锁,所以请求的数据以排他方式锁定时不会等待,读取的性能会获得改善,在修改数据的操作DELETE和UPDATE中需要复制行的版本,因而会相对降低写的性能。
SNAPSHOT: 读取数据时会确保获得事务启动时最近提交的可用行版本,这儿需要强调事务启动时的概念,比如两个事务A、B先后开启,B事务中修改数据并提交,这个数据修改是不会反应到事务A的,因为事务A获取额是在其开启前的行版本。值得一提的是,该级别可以防止更新冲突且不会造成死锁,比如同时在事务A和B中修改数据,系统会抛出异常,快照隔离事务由于更新冲突而终止。可以通过语句SET TRANSACTION ISOLATION LEVEL SNAPSHOT设置事务的隔离级别为SNAPSHOT。
READ COMMITTED SNAPSHOT: 它与SNAPSHOT的区别是,获取的"语句"启动时可用的最后提交的行版本,也就是在查询发起时最后提交的可用行版本,最后通过一个表格综述之前介绍的6种不同的隔离级别。
隔离级别 |
脏读 |
不可重复读 |
丢失更新 |
幻读 |
检测更新冲突 |
使用行版本控制 |
READ UNCOMMITTED |
Yes |
Yes |
Yes |
Yes |
No |
No |
READ COMMITTED |
No |
Yes |
Yes |
Yes |
No |
No |
READ COMMITTED SNAPSHOT |
No |
Yes |
Yes |
Yes |
No |
Yes |
REPEATABLE READ |
No |
No |
No |
Yes |
No |
No |
SERIALIZABLE |
No |
No |
No |
No |
No |
No |
SNAPSHOT |
No |
No |
No |
No |
Yes |
Yes |
这部分的最后补充一下数据库中死锁的概念,其和操作系统中学到的死锁改变一样,也是两个或多个进程相互阻塞的情况。在SQL SERVER中一旦出现死锁,系统会通过DEADLOCK_PRIORITY的死锁优先级来决定先终止哪一个进程,由于终止进程涉及事务的回滚等操作,会消耗一定的性能,通过更好的设计来避免死锁是更好的选择。
可编程对象比较多,包括变量、批、流元素、游标和临时表、用户定义函数、存储过程、触发器、动态SQL等概念,部分内容使用的场景较少,通过表格简述之,但对将对临时表这一常见并较难理解的概念进行细致介绍。
对象 | 解释与示例 |
变量 | DECLARE @i AS INT; SET @i = 10; |
批 | 表示一个单元分析和执行的命令组,变量存在于批的生命周期中,并且一个批中只能包含一个DDL语句。 USE TSQL2012; GO |
语句块和流元素 | 相对于PL/SQL,T-SQL中语法相对简单,结构完整性要求没有那么高 语句块: BEGIN END 逻辑流:IF BEGIN XXX END ELSE IF BEGIN XXX END ELSE BEGIN XXX END 循环流: WHILE @i < 10 BEGIN XXX END,支持BREAK和CONTINUE |
游标 | 游标使用的步骤:1.基于查询声明游标;2.打开游标;3.从游标记录中提取属性值给变量;4.遍历游标记录并迭代;5.关闭游标;6.释放游标 DECLARE C CURSOR FAST_FORWARD FOR SELECT custid, ordermonth, qty, FROM Sales.CustOrders ORDER BY custid, ordermonth OPEN C FETCH NEXT FROM C INTO @custid, @ordermonth, @qty SELECT @precustid = @custid, @runqty = 0; WHILE @@FETCH_STATUS = 0 BEGIN IF @custid <> @precustid SELECT @precustid = @custid, @runqty = 0 SET @runqty = @runqty + @qty INSERT INTO @Result VALUES(@custid, @ordermonth, @qty, @runqty) FETCH NEXT FROM C INTO @custid, @ordermonth, @qty END CLOSE C |
用户函数、存储过程 | 前者之前介绍内嵌表值函数时以有例子,这儿只介绍StoreProcedure,场景为获取某客户指定日期内订单并返回记录数 CREATE PROCEDURE Sales.GetCustomerOrders @custid AS INT, @fromdate AS DATETIME ='19010101', @todate AS DATETIME ='99991231', @numrows AS INT OUTPUT AS SET NOCOUNT NO SELECT orderid, custid, empid, orderdate FROM Sales.Orders WHERE custid = @custid AND orderdate > @fromdate AND orderdate < @todate SET @numrows = @@rowcount GO |
触发器 | CREATE TRIGGER trg_T1 ON dbo.T1 AFTER INSERT AS INSERT INTO dbo.T1_Audit(keycol, datacol) SELECT keycol, datacol FROM inserted GO |
动态SQL | DECLARE @sql AS VARCHAR(100) SET @sql = 'PRINT ''XIONGER''' EXEC(@sql),此外为了防止SQL注入,还可以使用sp_executesql来达到参数化存储过程数据参数的目的。 |
错误处理 | BEGIN TRY END TRY BEGIN CATCH IF XXX ELSE THROW END CATCH |
- 临时表
T-SQL支持3中类型的临时表,分别是本地临时表、全局临时表和表变量。本地临时表仅对创建它的会话可见,全局临时表对所有会话可见,表变量仅对当前会话的当前批有效,粒度更小,在T-SQL它也是实际的表(易误解为只存在内存)。临时表对于大量数据时性能更好,而表变量是处理少量数据最好选择,构建方式如下所示。
对象 |
解释与示例 |
本地临时表 |
IF OBJECT_ID('tempdbo.dbo.#MYTemp') IS NOT NULL CREATE TABLE #MYTemp(orderyear INT NOT NULL PRIMARY KEY) |
全局临时表 |
将本地临时表中的#换成##即可 |
表变量 |
DECLARE @MyOrder TABLE(orderyear INT NOT NULL PRIMARY KEY) |
补充部分常见SQL操作
元数据查询类型 |
解释与示例 |
创建架构 |
SET SCHEMA HR AUTHPRIZATION dbo |
最后附上英文原版参考书目(Microsoft SQL Server 2012 T-SQL Fundamentals)下载地址:http://pan.baidu.com/s/1eRbhnbk
非常感谢大家的阅读,系列文章链接如下,有T-SQL方面的任何疑问请随时和在下联系。
那些年我们写过的T-SQL(上篇):上篇介绍查询的基础,包括基本查询的逻辑顺序、联接和子查询
那些年我们写过的T-SQL(中篇):中篇介绍表表达式、集合运算符和开窗函数
那些年我们写过的T-SQL(下篇):下篇介绍数据修改、事务&并发和可编程对象
参考资料:
- (美)本咁. SQL Server 2012 T-SQL基础教程[M]. 北京:人民邮电出版社, 2013.
那些年我们写过的T-SQL(下篇)(转)的更多相关文章
- 那些年我们写过的T-SQL(下篇)
下篇的内容很多都会在工作中用到,尤其是可编程对象,那些年我们写过的存储过程,有木有?到目前为止很多大型传统企业仍然很依赖存储过程.这部分主要难理解的部分是事务和锁机制这块,本文会进行简单的阐述.虽然很 ...
- 那些年我们写过的T-SQL(上篇)
在当今这个多种不同数据库混用,各种不同语言不同框架融合的年代(一切为了降低成本并高效的提供服务),知识点多如牛毛.虽然大部分SQL脚本可以使用标准SQL来写,但在实际中,效率就是一切,因而每种不同厂商 ...
- 那些年我们写过的T-SQL(中篇)
中篇的重点在于,在复杂情况下使用表表达式的查询,尤其是公用表表达式(CTE),也就是非常方便的WITH AS XXX的应用,在SQL代码,这种方式至少可以提高一倍的工作效率.此外开窗函数ROW_NUM ...
- Oracle如何写出高效的SQL
转载:http://www.blogjava.net/ashutc/archive/2009/07/19/277215.html 1.选择最有效率的表明顺序(只在基于规则的优化器中有效) Oracle ...
- Oracle 如何写出高效的 SQL
转自:Oracle 如何写出高效的 SQL 要想写出高效的SQL 语句需要掌握一些基本原则,如果你违反了这些原则,一般情况下SQL 的性能将会很差. 1. 减少数据库访问次数连接数据库是非常耗时的,虽 ...
- SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比
原文:SQL点滴10-使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比 今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章 ...
- 理解SQL原理,写出高效的SQL语句
我们做软件开发的,大部分人都离不开跟数据库打交道,特别是erp开发的,跟数据库打交道更是频繁,存储过程动不动就是上千行,如果数据量大,人员流动大,那么我们还能保证下一段时间系统还能流畅的运行吗?我们还 ...
- 题目:写出一条SQL语句,查询工资高于10000,且与他所在部门的经理年龄相同的职工姓名。
create table Emp( eid char(20) primary key, ename char(20), age integer check (age > 0), did char ...
- 使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比
今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了.我从简单到复杂地写, ...
随机推荐
- iOS之UI--通讯录的实例关键知识技术点积累
通讯录的实例关键知识技术点积累 效果展示: 作为博文笔记,既然是笔记,目的是为了能够以后做这个项目能够快速上手,如果这是我下一次阅览这个博文笔记,那么我应该先空手从零开始做,需求也就是这个项目的展示效 ...
- 导出excel乱码问题
今天遇到一个问题,在用C#做导出excel的时候,出现excel乱码问题.百度了下. 发现问题如下: 非中文字符编码问题. 解决方法: 把输出的excel格式设置成UTF-8即可. 更改代码: Res ...
- H5文件操作API
引言 在之前我们操作本地文件都是使用flash.silverlight或者第三方的activeX插件等技术,由于使用了这些技术后就很难进行跨平台.或者跨浏览器.跨设备等情况下实现统一的表现,从另外一个 ...
- sql2008备份集中的数据库备份与现有的xxx数据库不同解决方法
原文链接:http://wncbl.cn/posts/1993c22/ 问题描述 今天在配置一个 ASP 站点时,导入以前的数据库备份文件,提示:sql2008备份集中的数据库备份与现有的xxx数据库 ...
- 给定a、b两个文件,各存放50亿个url,每个url各占用64字节,内存限制是4G,如何找出a、b文件共同的url?
给定a.b两个文件,各存放50亿个url,每个url各占用64字节,内存限制是4G,如何找出a.b文件共同的url? 可以估计每个文件的大小为5G*64=300G,远大于4G.所以不可能将其完全加载到 ...
- 使用ExposedObject对Asp.net MVC中匿名类型的JsonResult做单元测试
返回JsonResult是MVC中的常见返回值类型,而且简单方便的方式是结合匿名类型一起使用. 比如: public ActionResult PreviewEmail() { …… return J ...
- 5+ App开发入门指南
HTML5 Plus应用概述 HTML5 Plus移动App,简称5+App,是一种基于HTML.JS.CSS编写的运行于手机端的App,这种App可以通过扩展的JS API任意调用手机的原生能力,实 ...
- C# Ftp文件处理
1.创建文件夹 /// <summary> /// ftp创建文件夹(只能创建单层目录) /// </summary> /// <param name="Uri ...
- 为什么需要SQL Profile
为什么需要SQL Profile Why oracle need SQL Profiles,how it work and what are SQL Profiles... 使用DBMS_XPLAN. ...
- python模块调用
1.某个模块1被调用到另一个模块2的时候,当不想模块1中的某些代码在模块2中执行时,可以在模块一种添加如下代码: if __name__ == "__main__" ...