Hey!! Sky!

Apr 20, 2006

用 OPENROWSET 读取文件数据

    Joseph 今天碰到用 Sqlserver 直接从外部读取文件数据的问题,这个问题我以前也碰到过,找了半天只能找到将数据读入临时表再处理的办法,最后不了了之。其实这个功能在 Oracle 中可以用外部表很简单的解决。今天又 google 了一下(有事没事都找 google),找到了 OPENROWSET 这个好东西,看来 Sqlserver 还是有很多功能都没有用过,等待我们慢慢挖掘。


基本语法:


OPENROWSET ( 'provider_name'
    , { 'datasource' ; 'user_id' ; 'password'

        | 'provider_string' }
    , { [ catalog.] [ schema.] object
        | 'query' }
    )

详细介绍可以看 SQLSERVER 联机帮助。


具体操作:
1.创建一个 txt 文本,里面输入一些数据。第一行必须是列名,列之间必须用" , " 分隔(我试了下空格和制表符都不行,不知道这个间隔符可不可以该的),另外默认的数据类型是这样的:如果是纯数字会转换为相应的数字类型,还有字符的话会转换为字符类型,如果中间有 $ 符会转换为 money 类型(其他货币符号我没有尝试),如果在数据两边加上双引号("),会强制转为字符类型。


a.txt:
DMDUNIT,DMDGROUP,LOC
"1001","14","1401"

2.写查询语句:

select * from
OpenRowset('MSDASQL', 'Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=c:\;','select * from a.txt')

OK,搞定,联机帮助上说:“依据 OLE DB 提供程序的能力,还可以将 OPENROWSET 函数引用为 INSERT、UPDATE 或 DELETE 语句的目标表。”不过,'MSDASQL' 似乎没有提供这种能力,我尝试了 INSERT、UPDATE、DELETE 操作,返回错误:

服务器: 消息 7390,级别 16,状态 1,行 1
The requested operation could not be performed because the OLE DB provider 'MSDASQL' does not support the required transaction interface.
OLE DB error trace [OLE/DB Provider 'MSDASQL' IUnknown::QueryInterface returned 0x80004002].

如果你还不满足,想做些表连接什么的,没问题:

select A.* from DMDUNIT A
RIGHT OUTER JOIN
OpenRowset('MSDASQL', 'Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=c:\;','select * from a.txt') B
ON A.DMDUNIT=B.DMDUNIT

PS:其实用 OpenRowset 也可以解决不同服务器上数据库的表连接问题:

SELECT * FROM  表a a 
JOIN OPENROWSET('MSDASQL','DRIVER={SQL Server};SERVER=服务器2;UID=用户名;PWD=密码', 库B.所有者.表b) b on a.field=b.field

排序规则的问题:
    当用 OpenRowset 进行表连接的时候,一般都会碰到排序规则冲突的问题,不知道用 OpenRowset 查询时默认的排序规则是什么,不同排序规则的列做连接时会产生如下错误:

服务器: 消息 446,级别 16,状态 9,行 1
Cannot resolve collation conflict for equal to operation.

解决方法:
    在连接的列上制定排序规则:

select A.* from DMDUNIT A
WHERE NOT EXISTS
(SELECT 1 FROM OpenRowset('MSDASQL', 'Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=c:\;','select * from a.txt') B
WHERE A.DMDUNIT=B.a COLLATE Chinese_PRC_BIN)


参考资料:
OPENROWSET:
http://msdn2.microsoft.com/zh-cn/library/ms190312(SQL.90).aspx


使用排序规则:
http://msdn2.microsoft.com/zh-cn/library/ms187582(SQL.90).aspx


排序规则简介:
http://www.100pig.com/blog/article.asp?id=28


不同服务器数据库表连接:
http://u3.club.163.com/viewElite.m?catalogId=7023&eliteId=7023_1056e1a823c0f5a

Apr 04, 2006

关于 Checkpoint 和学习的体会

    关于 Checkpoint 的话题,一直都是谈论的焦点,对于 Complete Checkpoint 和 Incremental Checkpoint 也一直让初学者搞得稀里糊涂。

    今天重看 Checkpointing Instructors 这个 PPT 文档忽然有种豁然开朗的感觉,以前也尝试去研读过,可看到一半就放弃了,实在搞不懂其中的内在关系,不过通过一段时间对相关基础知识的学习,终于可以融汇贯通了。看来知识是需要慢慢积累的,不能一步登天。

    这里先偷个懒,具体对 checkpoint 的理解就不写了,只写几句重点:
1. checkpoint、dbwr、lgwr 这三个进程其实并没有实际的谁触发谁的关系,各自完成自己的任务,而 checkpoint 就是把 dbwr、lgwr 两者做的事情同步。

2. fast_start_mttr_target 参数不会指定 checkpoint 何时进行,感觉应该会触发 dbwr 才对,而 Incremental Checkpoint 只是在 control file 中记录 dbwr 已经完成的之后一个 RBA 的位置,不会写 datafile head。

3. logfile switch 只触发 Incremental Checkpoint ,但他会写 control file 和 datafile head;只有 alter system checkpoint 触发 Complete Checkpoint 。

参考资料:
Checkpointing Instructors
wanghai 的 checkpoint小议 http://www.cnoug.org/viewthread.php?tid=21969&highlight=&page=1 不过,他说日志切换时发生 Complete Checkpoint 似乎和实际不符,也可能是版本不同吧。
TOM 对 checkpoint 的解释:http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:19311485023372

Mar 31, 2006

PRODUCT_USER_PROFILE


SQL> conn sky/apspass@sdb
Connected.
SQL> insert into PRODUCT_USER_PROFILE (
  2  product, userid, attribute, char_value)
  3  values (
  4  'SQL*Plus','SKY','CREATE','DISABLED');


1 row created.


SQL> COMMIT;


Commit complete.


SQL> create table bb(x int);


Table created.


SQL> drop table bb;


Table dropped.


SQL> create table bb(x int);


Table created.


SQL> drop table bb;


Table dropped.


SQL> conn sky/apspass@sdb
Connected.
SQL> create table bb(x int);
SP2-0544: invalid command: create
SQL> select count(*) from PRODUCT_USER_PROFILE;


  COUNT(*)
----------
         1


SQL> delete from PRODUCT_USER_PROFILE
  2  where user_id='SKY';
where user_id='SKY'
      *
ERROR at line 2:
ORA-00904: invalid column name



SQL> ed
Wrote file afiedt.buf


  1  delete from PRODUCT_USER_PROFILE
  2* where userid='SKY'
SQL> /


1 row deleted.


SQL> commit;


Commit complete.


SQL> create table xx(bb int);
SP2-0544: invalid command: create
SQL> conn sky/apspass@sdb
Connected.
SQL> create table xx(bb int);


Table created.


SQL> drop table xx;


Table dropped.


SQL>


http://www.oracle.com.cn/viewthread.php?tid=86599


http://download-west.oracle.com/docs/cd/B10501_01/server.920/a90842/ch10.htm#1005767


 

WHENEVER SQLERROR 的使用

语法:

WHENEVER SQLERROR
{EXIT [SUCCESS|FAILURE|WARNING|n|variable|:BindVariable]
[COMMIT|ROLLBACK]|CONTINUE [COMMIT|ROLLBACK|NONE]}


作用:
    当 sql、pl/sql 执行过程中出现错误,则执行一些操作。注:不包括 sql*plus 命令的错误。

    出现错误时,可以执行两种操作 EXIT 和 CONTINUE,分别为退出 sql*plus 和 不退出。
     [SUCCESS|FAILURE|WARNING|n|variable|:BindVariable] 的具体作用没有搞清楚,可能是以什么样的方式退出 sql*plus 吧,如 SUCCESS、FAILURE 或者用变量,比如 SQL.SQLCODE。
    [COMMIT|ROLLBACK]:在退出 SQL*PLUS 前是提交事务还是回滚事务。
    [COMMIT|ROLLBACK|NONE]:如果不退出,那么也可以指定提交事务还是回滚事务,或者什么也不做。


实验:



SQL> whenever sqlerror exit SQL.SQLCODE rollback
SQL> select sysdate from dual;


SYSDATE
----------
2006-03-31


SQL> update aa set ff=5;
update aa set ff=5
       *
ERROR at line 1:
ORA-00942: table or view does not exist



Disconnected from Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.6.0 - Production


WHENEVER SQLERROR 生命周期应该是自该命令执行到 sql*plus 退出前的所有时段,下面实验可以证明:



C:\Documents and Settings\chent>sqlplus "sys/change_on_install@sbox as sysdba"


SQL*Plus: Release 9.2.0.6.0 - Production on Fri Mar 31 17:00:44 2006


Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.



Connected to:
Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.6.0 - Production


SQL> whenever sqlerror continue rollback
SQL> select sysdate from dual;


SYSDATE
----------
2006-03-31


SQL> update aa set ff=5;
update aa set ff=5
       *
ERROR at line 1:
ORA-00942: table or view does not exist


 


Rollback complete.


SQL> disconnect
Disconnected from Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.6.0 - Production
SQL> conn sys/change_on_install@sbox as sysdba
Connected.
SQL> update aa set ff=5;
update aa set ff=5
       *
ERROR at line 1:
ORA-00942: table or view does not exist


 


Rollback complete.


SQL> conn sys/change_on_install@mliv as sysdba
Connected.
SQL> update aa set ff=5;
update aa set ff=5
       *
ERROR at line 1:
ORA-00942: table or view does not exist


 


Rollback complete.


SQL> exit
Disconnected from Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
With the Partitioning option
JServer Release 8.1.7.0.0 - Production


C:\Documents and Settings\chent>sqlplus "sys/change_on_install@sbox as sysdba"


SQL*Plus: Release 9.2.0.6.0 - Production on Fri Mar 31 17:04:11 2006


Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.



Connected to:
Oracle9i Enterprise Edition Release 9.2.0.6.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.6.0 - Production


SQL> update aa set ff=5;
update aa set ff=5
       *
ERROR at line 1:
ORA-00942: table or view does not exist



SQL>


下面实验证明 WHENEVER SQLERROR 不影响 sql*plus 的命令错误:


SQL> whenever sqlerror exit sql.sqlcode rollback
SQL> print jdfk
SP2-0552: Bind variable "JDFK" not declared.


参考:
http://download-west.oracle.com/docs/cd/B10501_01/server.920/a90842/ch13.htm#1074195

exp/imp 一些参数的自我理解

一、所需的脚本:
       catexp.sql 或者 catalog.sql,后者包括了前者。


二、部分参数的理解:
1. BUFFER:
    决定了一次导入/导出多少行数据,只在 conventional path 下有效,既 direct=n,因为该方式下,数据会通过 sql 层的处理,需要一个 BUFFER 在内存中存储(可能是 Large Pool),然后整批的导入/导出,整批的导入/导出可以提高速度。BUFFER 可以通过以下公式计算:


BUFFER 大小 = 每行的大小 * 行数

    这样如果一次想导入/导出 100 行,那么 buffer 可以设置为 100 * 每行的大小。不过 包含 LONG, LOB, BFILE, REF, ROWID, LOGICAL ROWID, or DATE 等类型的行只能一行行导入/导出。


2. COMPRESS (default = y, only for export)
    如果 COMPRESS = y,那么,当导出表数据时,将不管 initial, next, pctincrease 等参数的影响,直接把所有数据定义在 extent 上,这样可以节省空间,消除碎片。在导入时,将按照 dump 文件中的定义来导入数据,既如果以 COMPRESS = y 导出,导入时就将所有数据放入一个 extent,反之亦然。
    如果 COMPRESS = n,那么将按照表的实际参数来分配 extent。
    注:LOB 类型不会被 COMPRESS。


3. CONSISTENT(default = n, only for export)
    如果 CONSISTENT = y,相当于导出时设定了 SET TRANSACTION READ ONLY 所有导出的数据都是一致的,不会受到导出过程中的数据更新影响。当该参数为 y 时,不能用 sys 或者任何其它 as sysdba 作为连接的用户。
    如果 CONSISTENT = n,那么一般来说每个表的数据导出过程是单个事务,但嵌套表的外部表和内部表分别属于不同的事务,分区表的不同分区也属于不同的事务。


4. DIRECT(default = n, only for export)
    如果使用 DIRECT = y,那么将用 direct path 方式读取数据,数据会被直接读出,绕过 SQL 命令处理层,该方式比 conventional path 快很多。


5. FEEDBACK(Default = 0)
    在导入/导出时显示进度,每几行显示一个进度格。


6. FILE FILESIZE
    FILE 默认值 expdat.dmp,FILESIZE 的默认值是允许的 maximum size(根据不同的操作系统和 Oracle 版本而不同,可能有 2G 的最大限制)。
    当使用一个 DUMP 文件时,只需要指定 FILE 参数,如果要使用多个 DUMP 文件可以将两个参数一起使用。
    FILESIZE 指定每个 DUMP 文件的最大值,如果不指定,或者该参数为 0,那么不管 FILE 参数设置了多少个文件,都只将导出到一个文件,或从一个文件中导入。
    FILE 指定每个 DUMP 文件的名称,导出时,如果数据的总大小 / FILESIZE > FILE 中指定的文件个数,那么会被要求输入另外的 DUMP 文件。


7. QUERY(default = none, only for export)
    在使用表模式导出数据时,设定导出的条件,该条件是应用到所有的表上的,如果指定的列不在其中任何一个表中都会报错。该参数不能用在 DIRECT = y 方式下,也不影响嵌套表中的内部表。


8. TABLES(default = none)
    以表模式导入/导出数据,可以指定要导入/导出的表或分区,格式:


schemaname.tablename:partition_name
schemaname.tablename:subpartition_name

9. TTS_FULL_CHECK(default = FALSE, only for export)
    在表空间迁移方式下指定该参数,会检测该表空间集是不是自独立的,内部的对象不依赖于外部对象,外部的对象也不依赖于内部对象。指定该参数来迁移表空间前,最好使用 dbms_tts.transport_set_check 来检测表空间集是不是自独立的,使用 dbms_tts 包需要先运行 dbmsplts.sql。具体步骤见:Transporting Tablespaces Between Databases


暂时写这些,以后碰到其他问题再补充。


参考:
http://download-west.oracle.com/docs/cd/B10501_01/server.920/a96652/toc.htm