2009年12月10日 星期四

[SQL Server]序號(Sequence)產生器(可依不同需要開發)

需求:
1. 取得目前的CUR_SEQ
2. New CUR_SEQ= CUR_SEQ + 1 (超過6位數,會重置為1)
3. Update New CUR_STAN
4. 輸出 New CUR_STAN
限制: 確保每個Client取得的CUR_SEQ號碼牌為唯一...

需要如下方的結果:(A+B+SEQNO)
ID NO CUR_SEQ
----- ---- -------------
8 0 1
8 1 1
8 2 1
(3 個資料列受到影響)

想了一下,若要確保每個用戶端在同時間取同一組序號時,不得有重覆取得的問題,
但又不能影響其它組取得序號,因此覺得使用with(ROWLOCK)會是較好的決定:

With(ROWLOCK) : 若有table有規畫PK constraint或index時,則只會lock住該筆記錄,
不會影響其它組的資料存取。
ROWLOCK其實也並不是直接對該筆資料列作鎖定,而是針對其INDEX的KEY值作鎖定。
下方有online book說法
/*
Lock hints ROWLOCK, UPDLOCK, AND XLOCK that acquire row-level locks may place locks on index keys rather than the actual data rows. For example, if a table has a nonclustered index, and a SELECT statement using a lock hint is handled by a covering index, a lock is acquired on the index key in the covering index rather than on the data row in the base table.
*/

我的作法:
A.新增SEQUENCE Table: SEQNO



CREATE TABLE SEQNO(ID NVARCHAR(5) NOT NULL, NO NVARCHAR(2) NOT NULL, CUR_SEQ NUMERIC(6) NOT NULL, CONSTRAINT PK_SEQNO PRIMARY KEY (ID,NO));


B.新增SEQUENCE PROCEDURE:SP_SEQNO
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SP_SEQNO]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[SP_SEQNO]
GO

CREATE PROCEDURE SP_SEQNO (
@ID nvarchar(5),
@NO nvarchar(2),
@MAXSEQ NUMERIC(6) output
)
AS
DECLARE @CURSEQ NUMERIC(6);
SET @CURSEQ = 0;
BEGIN
/* 初始值*/
IF NOT EXISTS (SELECT * FROM SEQNO WHERE ID=@ID AND NO=@NO )
BEGIN
INSERT INTO SEQNO (ID,NO,CUR_SEQ) VALUES(@ID,@NO,0);

UPDATE SEQNO WITH(ROWLOCK)
SET @MAXSEQ=CUR_SEQ= CUR_SEQ+1
WHERE ID = @ID
AND NO= @NO;
END
ELSE
BEGIN
/*抓出目前的SEQNO放至@CURSEQ,最大值限制判斷 */
SELECT @CURSEQ = CUR_SEQ
FROM SEQNO WITH(ROWLOCK)
WHERE ID = @ID
AND NO= @NO

/* 若超過6位數需重置為1*/
IF (@CURSEQ =999999)
BEGIN

UPDATE SEQNO WITH(ROWLOCK)
SET @MAXSEQ=CUR_SEQ=0 WHERE ID =@ID AND NO =@NO;

END
ELSE
IF (@CURSEQ<999999)
BEGIN
UPDATE SEQNO WITH(ROWLOCK)
SET @MAXSEQ=CUR_SEQ=CUR_SEQ+1 WHERE ID =@ID AND NO =@NO;
END
END
END

參考資料: url= lock explain:http://technet.microsoft.com/en-us/library/ms187373.aspx
recieve varaible output valus from procedure: 如何接收 Store Procedure 的傳回值

[MSSQL] IF EXISTS ...END寫法架構

IF EXISTS (SELECT * FROM Table1)BEGIN
...............
END
ELSE
BEGIN
.............
END

2009年12月8日 星期二

Oracle處理DATE及TIMESTAMP需注意的地方

oracle官方說法上的確證明了~
基本上Date 型態精準度只能到second,不含fractional seconds 或time zone,
而timestamp可支援frational seconds 0~9位,default是到小數點六位。請再往下看(可跳過例子)

舉例: Table: test( ttime DATE,ttimestamp TIMESTAMP)

利用"TO_DATE()"函數
一定要使用"to_timestamp()" 函數才能將含有毫秒或到奈秒的資料塞進timestamp型態的欄位中。


就目前實驗的結果就顯示
TO_TIMESTAMP才可支援到秒數小數點後9位。TO_DATE是不行的!

下面是oracle文件內建型態說明: 請看date及timestamp說明




若想知道oracle對日期的描述字元有哪些格式,請參考:
http://download.oracle.com/docs/cd/B13789_01/server.101/b10758.pdf
[7-3頁 Datetime Format Models]

由於oracle的session及database層級的參數設定,會以session層級為優先。
所以如果有權限的情況下想了解目前database及client端的format設定時,
可利用query下方指令。
Database層:
select * from nls_database_parameter;
 
Session層:
select * from nls_session_parameter;
 
若想修改session層的設定:
alter session set nls_data_format=yyyy-mm-dd;
 







2009年12月7日 星期一

Microsoft Offcie -Excel 數字的尾數自動調整為0

Excel 貼上數字型的格式時,例如像信用卡號的16個字元長度,excel會自動調整為0
例如 4394112233110022 -->會變成 4394112233110020
不管我將儲存格格式更改為數字去掉小數點,尾數都會自動調整為0,
後來用了好久,在office online book上面查詢後,才發現原來
office excel在數字的精準度上面,只能支援15位的有效數字,若要輸入信用卡號,且要完整顯示的話~有兩個作法
1.儲存格欄位格式需調整為是"文字"。
2.利用[ ' ]單引號加在數字前方,強迫指定為文字格式。
這樣就能正確顯示出信用卡號了!

參考url:http://office.microsoft.com/zh-tw/excel/HA102748231028.aspx#5

2009年7月27日 星期一

Oracle 9i for Windows Platform 32bit 解決Memory-SGA 最多有1.7G限制的設定(AWE)

環境 : Windows 2003 Enterprise Edition SP2 (32bit Windows platform)
使用windows cluster機制& Oracle Failsafe實現oracle instance cluster。
Oracle: Oracle Enterprise Edition 9i (9.2.0.1 patch to 9208)
Memory: 8G RAM


由於Oracle on 32-bit Windows platforms,限制預設使用的SGA設定最多不能2G(實作上1.6G),而metalink上有解決方法,在此提出並將實作結果記錄下來:

Metalink doc:

Subject: Implementing Address Windowing Extensions (AWE) or VLM on Windows Platforms
Doc Id: 225349.1


設置的方式有2,稱之為"PAE" (Physical Address Extensions) 或"AWE" (Address Windowing Extensions) 這兩種方式可以交替使用。
而AWE的設定前提條件: Physical RAM在4G以上。
可使用的平台有
* Windows 2000 Datacenter Server
* Windows 2000 Advanced Server
* Windows 2003 Data Center Edition (32-Bit)
* Windows 2003 Enterprise Edition (32-Bit)
在以上的OS 平台,AWE可內嵌設定於OS層,因此不需要特別指定driver去驅動,就可使用多餘的memory。
而不能使用的平台有:
* Windows 2000 Server (Standard)
* Windows 2000 Professional
* Windows XP Home Edition
* Windows XP Professional
* Windows 2003 Standard Edition
* Windows 2003 Web Edition

ps: 64bit的windows platform 不需要AWE的設定,因為64bit-Windows platforms上,單一process最高可使用到8 TeraBytes的memory。

AWE in 32Bit RDMS release 版本為:
* Oracle 8.1.6.x
* Oracle 8.1.7.x
* Oracle 9.2.x
* Oracle 10.1.x
* Oracle 10.2.x
ps: Oracle does NOT implement AWE support in release 9.0.1.x
而且只限制Enterprise Edition and Standard Edition 才可生效!

##設定步驟##
1. OS level:
  • C:\boot.ini 修改內容:
[operating systems]multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows Server 2003, Enterprise" /3GB /PAE /noexecute=optout /fastdetect
"/3GB" 及"/PAE"同時設定的話,則Address space for ORACLE.exe會是3G,且要注意主機RAM是否最多到16G,若超過的話~則建議只使用一種即可。
  • 確認user的系統權限

在服務中設定的oracle SID 登入身份必需要被授與" Lock Page in Memory"的系統權限,一般oracle SID service登入身份會是" LocalSystem" account,請確認LocalSystem的帳號擁有此系統權限。

設定方式: 開始\控制台\系統管理工具\本機安全性原則-->選擇--> "本機原則\使用者權利指派\鎖定記憶體分頁",

在本機安全性設定新增使用者或群組,並加入該使用者。這個設定是為了保留process的實際記憶體分頁,阻止系統將資料分頁至virtual虛擬記憶體中,這種方式會減少實際記憶體的可使用量。設定後記得重啟service。

  • 基碼修改(新增: AWE_WINDOW_MEMORY)

在HKLM\Software\Oracle\HomeX 新增一個基碼(reg_sz格式),計算單位為bytes,default為1g,因此新增值 AWE_WINDOW_MEMORY=1073741824

2. Database/Instance level:

  • init.ora

Add [ USE_INDIRECT_DATA_BUFFERS=TRUE ]
Add [DB_BLOCK_BUFFERS= /8192(db_block_size)]

注意: 若DB_CACHE_SIZE與USE_INDIRECT_DATA_BUFFERS=TRUE 同時存在時,會出現ORA-00385: cannot enable Very Large Memory with new buffer cache 的錯誤發生。

因此只要設置DB_BLOCK_BUFFERS,移除DB_CACHE_SIZE的參數即可。其實buffer cache size的大小設定還要保留4G 的RAM下來給os或其它應用程式使用,因此可算出buffer cache最多可設定的值為多少。

舉例說明: 8G RAM,use Default value of 1G for AWE_WINDOW_MEMORY,buffer cache最多可以設至的公式

Max Buffer cache (Total Ram-4G + AWE_WINDOW_MEMORY) =8G-4G+1G=5G

而db block size=8192 ,則db_block_buffers的設定最大值為5G/8192 =5368709120/8192=655360

3. 重新啟動instance。

##完成設定##

總SGA size= ((db_block_buffers*buffer size ) + (shared_pool_size+large_pool_size +java_pool_size+log_buffers) +1MB

SGA +oracle 臨界值不能超過可用的虛擬記憶體,因為虛擬記憶體要計算buffer cache=db_block_buffer*db_block_size得出值。

註: 「監控mapping memory狀態」

可使用下列sql:select * from v$sysstat where statistic# in (154, 155);

10gr2: select statistic#, name from v$sysstat where name like '%map %';

若在10g要設定USER_INDIRECT_DATA_BUFFER,也就是使用AWE,則INIT.ORA不能使用SGA_TARGET的參數,SGA_TARGET=0。

2009年6月5日 星期五

ORA-12638 身份證明檢索失敗-解決原因與方法

今天在裝ap server時,遇到sqlplus id/pass@SID時出現 ORA-12638 身份證明檢索失敗的error。

後來在客戶端沒有外網,也沒遇這樣的問題~call friend幫忙查一下,將

Sqlnet.Authentication_Services=(NTS) 改為Sqlnet.Authentication_Services=(NONE)

就可以正常連線了!



後來查了一下官方的文件

SQLNET.AUTHENTICATION_SERVICES
Purpose


Use the parameter SQLNET.AUTHENTICATION_SERVICES to enable one or more authentication services. If authentication has been installed, it is recommended that this parameter be set to either none or to one of the authentication methods.
.Default
.None
.Values
Authentication Methods Available with Oracle Net Services:
none -- for no authentication methods. A valid username and password can be used to access the database.
all -- for all authentication methods
nts -- for Windows NT native authentication


Authentication Methods Available with Oracle Advanced Security:
kerberos5 for Kerberos authentication
cybersafe for Cybersafe authentication
radius for RADIUS authentication
dcegssapi for DCE GSSAPI authentication

See Also:
Oracle Advanced Security Administrator's Guide



表示這是一種認證方式,如果是NTS就是用windows的認證模式,表示登入sysdba時,不需要輸入帳號密碼即可登入,若對於Oracle on windows cluster來說,使用的一組virtual IP 本來就不能使用windows認證方式進入database,故解決辦法就是改為none(表示只要在oracle資料庫的使用者、密碼對了~就可以登入了)

要注意一件事!!這個設定只適合在AP Client端作設定,如果在DB server端作此設定的話,會造成"conn / as sysdba" 匿名登入時會失效!