数据库设计首要任务之一是选择数据库的字符集,因为这关系到你的数据是以什么编码存储的,你的数据库支持什么语言等等….
1.什么是字符集(Character Set)
所谓字符集,顾名思义就是将一组字符,比如:文字字符,象形文字,符号,标点符号,控制符等通过一定的编码组成一个集合。不同的字符集有不同的编码方式,比如最常见的是ASCII,ZHS16GBK等等,它们的编码方式不一样,所包含的字符也不一样。
不同的字符集不仅决定你的数据库支持什么样的语言,还同时影响你:
1).如何创建你的数据库对象
2).如何开发你的应用程序来处理字符数据
3).数据库如何跟操作系统进行工作
4).数据库性能
5).存储数据所需的空间 (more…)
最近在EXP一用户的数据时出现如下错误:
ORA-00600: internal error code, arguments: [unable to load XDB library], [], [],
在GOOGLE上查找了一下,原来是LD_LIBRARY_PATH这个环境变量设错了,将其设置为:
LD_LIBRARY_PATH=/opt/app/ oracle /10g/lib
问题解决!
相关文档:Metalink Doc ID(351650.1)
Applies to:
———————-
Enterprise Manager for RDBMS - Version: 9.2.0 to 10.2.0
oracle Server - Enterprise Edition - Version: 9.2.0 to 10.2.0
oracle Server - Personal Edition - Version: 9.2.0 to 10.2.0
oracle Server - Standard Edition - Version: 9.2.0 to 10.2.0
Solaris Operating System (SPARC 64-bit)
This problem can occur on any Unix platform. (more…)
我们知道在MS SQL中CHAR(N)或VARCHAR(N)的N是指Bytes,而不是字符的个数,那么在 oracle 中(CHAR或VARCHAR2),这个N到底是字符的个数还是字节长度?
在 oracle 中这个N既可以是Bytes也可以是Characters,那么如何去指定它是哪一种呢?有两种方法:
1.在CHAR或VARCHAR2中明确指定
如:CHAR(10 CHAR),VARCHAR2(20 CHAR),CHAR(10 BYTE),VARCHAR2(20 BYTE)
2.在初始化参数中指定
可以在初始化参数中指定NLS_LENGTH_SEMANTICS=’CHAR’或’BYTE’来确定
默认情况下这个参数是BYTE
那么这两种方式有什么关系和优缺点呢? (more…)
前几天一同事问我怎么样用简单的SQL语句UPDATE如下记录:
ID Category
——————-
1 A
2
3 B
4
5
6 C
7
UPDATE成:
ID Category
——————-
1 A
2 A
3 B
4 B
5 B
6 C
7 C
其中ID是按照从小到大顺序排列的。
当然该问题用游标很容易实现,类似如下:
DECLARE @ID INT
DECLARE @Category VARCHAR(10)
DECLARE Cur_user CURSOR
FOR SELECT ID,Category FROM Mosfet$
OPEN Cur_user
FETCH NEXT FROM Cur_user INTO @ID,@Category
WHILE @@FETCH_STATUS = 0
BEGIN
IF @Category <>” set @Category1 = @Category
UPDATE Mosfet$ SET Category = @Category1 where ID = @ID
FETCH NEXT FROM Cur_user INTO @ID,@Category
END
DEALLOCATE Cur_user
但当记录一多的时候效率太差,那怎么实现快速更新呢?我们知道UPDATE时SQL SERVER是一条一条进行UPDATE的,我们仔细看看表的数据结构,其实只要在UPDATE时能有个变量保存上一条记录的Category的值就能解决问题,那UPDATE语句有没有这个功能呢?查一下帮助:
UPDATE
{
table_name WITH ( < table_hint_limited > [ ...n ] )
| view_name
| rowset_function_limited
}
SET
{ column_name = { expression | DEFAULT | NULL }
| @variable = expression
| @variable = column = expression } [ ,...n ]
{ { [ FROM { < table_source > } [ ,...n ] ]
[ WHERE
< search_condition > ] }
|
[ WHERE CURRENT OF
{ { [ GLOBAL ] cursor_name } | cursor_variable_name }
] }
[ OPTION ( < query_hint > [ ,...n ] ) ]
看SET部分:
@variable
已声明的变量,该变量将设置为 expression 所返回的值。
SET @variable = column = expression 将变量设置为与列相同的值。这与 SET @variable = column, column = expression 不同,后者将变量设置为列更新前的值
注意粗体部分,正好符合我们的要求:)
简单的语句如下:
DECLARE @Category VARCHAR(10)
SELECT @Category=(SELECT TOP 1 Category FROM TEST WHERE Category<>”)–取第一条非空记录的Category的值
UPDATE Test
SET @Category=CASE WHEN CATEGORY =” THEN @Category ELSE CATEGORY END,CATEGORY=@Category
FROM Test
测试如下:
CREATE TABLE TEST
(ID INT,
Category VARCHAR(10))
INSERT INTO TEST
SELECT 1,’A’
UNION ALL
SELECT 2,”
UNION ALL
SELECT 3,’B’
UNION ALL
SELECT 4,”
UNION ALL
SELECT 5,”
UNION ALL
SELECT 6,’C’
UNION ALL
SELECT 7,”
SELECT *FROM TEST
ID Category
———– ———-
1 A
2
3 B
4
5
6 C
7
DECLARE @Category VARCHAR(10)
SELECT @Category=(SELECT TOP 1 Category FROM TEST WHERE Category<>”)–取第一条非空记录的Category的值
UPDATE Test
SET @Category=CASE WHEN CATEGORY =” THEN @Category ELSE CATEGORY END,CATEGORY=@Category
FROM Test
SELECT * FROM TEST
ID Category
———– ———-
1 A
2 A
3 B
4 B
5 B
6 C
7 C
结果符合我们的要求,而且性能很好。
当然该语句还是有点问题的,在哪里呢?就是数据返回的顺序问题,我们知道按照关系型数据库理论,表里面的数据严格来说是没有顺序的,而该语句要成功执行就有赖于数据的顺序,那怎么让UPDATE按我们的顺序进行UPDATE呢?关于这个问题,我会再详细说明,这里给出一个方法,在ID上建一个集群索引,这个索引按照ID从小到大排序,这样就能确保数据按ID从小到大的顺序进行UPDATE。
CREATE CLUSTERED INDEX ID_IX ON TEST(ID ASC)
其实该问题并不复杂,只要熟悉SQL语句的用法及认真研究需求就能写出简单高效的SQL语句,这让我想起TOM的名言:
能用一条SQL语句实现的就尽量用一条语句去实现。
一. 什么是数据库的坏块
首先我们来大概看一下数据库块的格式和结构:
数据库的数据块有固定的格式和结构,分三层:
Cache layer
Transaction layer
Data layer
在我们对数据块进行读取写入操作的时候,数据库会对要读写的数据块做一致性的检查,其中包括:数据块的类型、数据块的地址信息、数据块的SCN号以及数据块的头部和尾部。如果发现其中有不一致的信息,那数据库就会标记这个数据块为坏块了。数据库的坏块分为两种:逻辑坏块和物理坏块
逻辑坏块(Logically Corrupt):example: the block was corrupted by an oracle internal error but does not appear to be media corrupt
物理坏块(Media Corrupt):incorrect checksum/wrong data block address/impossible block type (more…)
一客户在查询数据时报如下错误:
SQL> select count(*) from sa.g_sn_travel;
select count(*) from sa.g_sn_travel
*
ERROR 位于第 1 行:
ORA-08103: object no longer exists
用analyze分析该表,出现如下提示:
SQL> analyze table sa.g_sn_travel validate structure cascade;
analyze table sa.g_sn_travel validate structure cascade
*
ERROR 位于第 1 行:
ORA-01499: table/index cross reference failure - see trace file
查看对应的trace file发现该表的索引和表的数据出现不一致,于是重新创建该Index解决问题。 (more…)
我们知道在SQL SERVER中有datediff可以返回两个日期之间的时间间隔,但在 oracle 中却不存在这样的函数,那要怎么实现呢?我们分两种情况讨论:
1.只是粗略返回相隔的天数
我们知道在 oracle 中两个日期相减返回的就是相差的天数,当然这个天数未必是整数,它会把两个日期相差的时分秒折算成天数
SQL> SELECT SYSDATE-HIREDATE FROM EMP;
SYSDATE-HIREDATE
—————-
3.12123843
9316.66291
9314.66291
9275.66291
9096.66291
9246.66291
9207.66291
9046.66291
9116.66291
9030.66291
9030.66291
8979.66291
此时我们可以用TRUNC函数去获取我们所要得到的天数: (more…)
ORA-1555错误简单的说就是针对一个数据块产生一致读时发生了错误。一致读就是指 oracle 利用回滚段来临时重构一个和事务或查询开始时的块状态相同的快照块的过程。如果一个块改变了多次,可能就会有多个快照块的。
一个事务或查询开始执行时, oracle 会产生一个SCN来记录这个开始时刻点,这个SCN也就叫做SNAPSHOT SCN。 oracle 仅仅看基于SNAPSHOT SCN的快照记录。如果块中有活动的事务或BLOCK SCN> SNAPSHOT SCN时,就产生了一致读。如果是没有活动的事务但没有产生COMMIT SCN的块,先产生DELAY BLOCK CLEANOUT,再比较COMMIT SCN与SNAPSHOT SCN的大小,如果COMMIT SCN小于SNAPSHOT SCN则直接使用该块,否则要产生一致读。
产生ORA-1555的可能情况:
(1) 一个长时间运行的查询,并同时针对查询需要的块有DML处理
当一个长时间的查询开始执行时,查询所需要的一个数据块被修改并递交了,这个块是需要一致读的,但因为该DML事务已递交了,所以保留前映像的回滚段SLOT可以被另外的事务使用,这个查询事务耗时非常长,在这个时间段中,很可能该SLOT被另外的事务使用而把原值给覆盖了,所以当查询执行到该块时,该块的SNAPSHOT SCN时的值已经找不到了,报ORA-1555错误。 (more…)
我们从一个用户请求开始讲, oracle 的完整的工作机制是怎样的,首先一个用户进程发出一个连接请求,如果使用的是主机命名或者是本地服务命中的主机名使用的是机器名(非IP地址),那么这个请求都会通过DNS服务器或HOST文件的服务名解析然后传送到 oracle 监听进程,监听进程接收到用户请求后会采取两种方式来处理这个用户请求,下面我们分专用服务器和共享服务器分别采用这两种方式时的情况来讲:
专用服务器模式下:一种方式是监听进程接收到用户进程请求后,产生一个新的专用服务器进程,并且将对用户进程的所有控制信息传给此服务器进程,也就是说新建的服务器进程继承了监听进程的信息,然后服务器进程给用户进程发一个RESEND包,通知用户进程可以开始给它发信息了,用户进程给这个新建的服务器进程发一个CONNECT包,服务器进程再以ACCEPT包回应用户进程,致此,用户进程正式与服务器进程确定连接。我们把这种连接叫做HAND-OFF连接,也叫转换连接。另一种方式是监听进程接收到用户进程的请求后产生一个新的专用服务器进程,这个服务器进程选用一个TCP/IP端口来控制与用户进程的交互,然后将此信息回传给监听进程,监听进程再将此信息传给用户进程,用户进程使用这个端口给服务器进程发送一个CONNECT包,服务器进程再给用户进程发送一个ACCEPT包,致此,用户进程可以正式向服务器进程发送信息了。这种方式我们叫做重定向连接。HAND-OFF连接需要系统平台具有进程继承的能力,为了使WINDOWS NT/2000支持HAND-OFF必须在HKEY_LOCAL_MACHINE>SOFTWARE> oracle >HOMEX中设置USE_SHARED_SOCKET。 (more…)
Recent Comments: