顯示具有 Database 標籤的文章。 顯示所有文章
顯示具有 Database 標籤的文章。 顯示所有文章

12月 26, 2024

Java 透過 Oracle Wallet 連線資料庫

1. 需要準備 Oracle JDBC Drivers full版 (Wallet會用到oraclepki.jar等套件)

2. 編譯方式
D:\jdk17\bin\javac.exe -cp .;D:\ojdbc17-full\ojdbc17.jar OraDBConn.java
D:\jdk17\bin\java.exe  -cp .;D:\ojdbc17-full\ojdbc17.jar OraDBConn
3. 範例程式碼 (OraDBConn.java)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.ResultSet;
import java.sql.Statement;

public class OraDBConn {
  public static void main(String[] args) {
    // Database connection information
    String host = "10.18.1.1";
    String port = "1522";
    String serviceName = "SNAME";
    String db_user_id  = "TESTID";
    String db_user_pwd = "2wsx3edc";
    String jdbcUrl = "jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=" +
                     "(PROTOCOL=TCPS)(HOST=" + host + ")(PORT=" + port + ")))" + 
                     "(CONNECT_DATA=(SERVICE_NAME=" + serviceName + ")))";    
    // Need [cwallet.sso] file for SSO authentication
    System.setProperty("oracle.net.wallet_location", "D:\\wallet");    
    try 
    {
      // Establish a connection using the Oracle Wallet
      Connection connection = 
        DriverManager.getConnection(jdbcUrl, db_user_id, db_user_pwd);     
      System.out.println("Connection established successfully!");
      
      Statement stmt    = connection.createStatement();
      String    sqlcode = "SELECT * FROM OWNER.Table13 WHERE ROWNUM <= 3";
      ResultSet rs      = stmt.executeQuery(sqlcode);           
      while(rs.next())  System.out.println(rs.getString(5) + "\t");
      
      connection.close();
    } 
    catch (SQLException e) { 
      e.printStackTrace(); System.out.println("Failed connect."); }
  }
}

11月 04, 2014

將 MysQL 中所有資料列塞進 Memory 內加快查詢

有點暴力的作法,基本上就是將資料存一份在磁碟中,於資料庫啟動後把所有資料全倒進記憶體內,加快查詢速度。

(1) 調整 heap table 的大小,因為 MySQL 的 Memory Engine 使用這個資料結構。
# my.ini
max_heap_table_size = 512MB
(2) 將資料倒入
# 建立表格 mem_parkTable 其 Schema 延用 parkTable
mysql> CREATE TABLE mem_parkTable LIKE parkTable;

# 設定儲存引擎為記憶體
mysql> ALTER TABLE mem_parkTable ENGINE = MEMORY;

# 開始倒資料進來
mysql> INSERT INTO mem_parkTable SELECT * FROM parkTable;
(3) 基本上到這邊就完成了,注意一下如果 MySQL 重新啟動後,在記憶體內的資料會完全不見(廢話),需要重新匯入。

10月 29, 2014

匯入「100萬筆」記錄至 MySQL 資料庫

手上的樣本檔有150萬筆資料量,檔案(csv格式)大小約100MB,用 phpMyAdmin 匯入當然是失敗!硬著頭皮看有什麼指令可用...

(1) 因為安全考量 MySQL 預設關閉從檔案匯入資料,所以先調整 my.ini 設定檔:
[mysql]
local-infile=1
[mysqld]
local-infile=1
(2) 建立資料庫(parkDB)後,再建立表格(parkTable)存放記錄:
'第一欄位序號(SN)作為主鍵並具遞增性質
CREATE TABLE parkTable
( SN integer AUTO_INCREMENT PRIMARY KEY ,
  PARK_DATE varchar(10), PARK_TIME varchar(10),
  CAR_NO varchar(10), BRAND varchar(20),
  COLOR varchar(20) );
(3) 從檔案匯入資料庫
# mysql -u root -p
mysql> use parkDB
mysql> LOAD DATA LOCAL INFILE 'SOURCE.csv' INTO TABLE parkTable
    -> FIELDS TERMINATED BY ',' ENCLOSED BY '"' LINES TERMINATED BY '\n'
    -> (PARK_DATE, PARK_TIME, CAR_NO, BRAND, COLOR);
參數相關說明:
  • 從檔案 SOURCE.csv 匯入資料到表格(parkTable)
  • 欄位區分是以逗號(,)來作識別。例如資料 A,B,C 看作三欄。
  • 每欄資料是用雙引號(")圍起來。例如資料 "XYZ-123"。
  • 換行符號是 "\n"
  • 匯入資料對應欄位為 (PARK_DATE, PARK_TIME ...)
(4) 資料量很大時,為加快查詢請記得建立索引。
'索引欄位 CAR_NO
CREATE INDEX idx_CAR_NO ON parkTable (CAR_NO);

9月 22, 2014

SQL UPSERT 語法

在 SQL 中的 UPSERT 語法指的是:若資料不存在則新增一筆,否則更新已存在資料。原文見維基百科 Merge (SQL)條目
A relational database management system uses SQL MERGE (also called upsert) statements to INSERT new records or UPDATE existing records depending on whether or not a condition matches.
在 MySQL 實作語法為 INSERT ... ON DUPLICATE KEY UPDATE
實際用法:
INSERT INTO table (IDX, IPAddr, Msg, Status)
VALUES ('1', '127.0.0.1', 'foorbar', 'UNSENT')
ON DUPLICATE KEY UPDATE Status = 'SENT'
說明:
  • 若記錄不存在,則新增一筆 (1, 127.0.0.1, 'foorbar', 'UNSENT') 
  • 如果原記錄存在,修正更新為 (1, 127.0.0.1, 'foorbar', 'SENT')
針對資料列存在與否,不須仰賴其他程式進行判斷,直接透過 SQL 處理。若資料列不存在,則進行插入(INSERT)動作,否則進行更新(UPDATE)動作。

實例更新(Jan. 22, 2018):

資料表 daily_transaction 結構 ( idx, date, qty, amount )
  • idx 為主鍵自動遞增(AUTO INCREMENT)
  • date 為唯一鍵(UNIQUE key)
  • qty 代表件數、amount 代表總金額
在此例中只在乎日期(date)是否存在、不管 idx 值;存在則更新資料,否則插入資料:
INSERT INTO daily_transaction (date, qty, amount)  //date 是唯一鍵
VALUES('1070122', '168', '368100')
ON DUPLICATE KEY UPDATE qty='168', amount='368100';

9月 20, 2014

透過 PHP 連線 Oracle 資料庫

先談比較容易處理的 PHP 語法


在 Oracle 資料庫系統中,連線方式有兩種區別:Service Name 與 SID,不要弄錯了。手上的開發環境以 Service Name 為例。
  • 語法範例 (Oracle 11g 資料庫):
  • $db_id = "ORACLE-USER";
    $db_pwd = "ORACLE-PASSWORD";
    $oracle_db = "(DESCRIPTION = (ADDRESS_LIST = 
      (ADDRESS = (PROTOCOL = TCP)(HOST=10.1.1.1)(PORT=1521) ) )
      (CONNECT_DATA = (SERVICE_NAME=LODA) ) )";
    
    /* Go, Using UTF-8 Encoding */
    $conn = oci_connect($db_id, $db_pwd, $oracle_db, 'utf8');  
    $sql = "SELECT X,Y,Z FROM TABLE";
    
    if( !$conn ) { print_r (oci_error()); /* ErrCode */ }
    else
    {
     try
     {
      $stid=oci_parse($conn, $sql);
      oci_execute($stid);  /* Do Query */
      while( $row = oci_fetch_array($stid, OCI_BOTH) )
      { 
       $X = $row['X']; /* Fetch result, encoding to BIG5 */ 
       $Y_big5 = mb_convert_encoding ($row['Y'],"big5","utf-8");
      }
     }
     catch (Exception $err) { echo $err->getMessage(); }
    }
    /* Connection release */
    if($stid){ oci_free_statement($stid); }
    if($conn){ oci_close($conn); }
    
  • 指令不難,但在編碼的地方卡了一下,因為 Client 端只收 Big5 編碼。後來翻到函式 mb_convert_encoding($str, newEncode, oriEnconde) 用來轉換,所以順利解決。

再來是卡關好幾次的環境設定


因為在 Windows 環境下使用了 Uniform Server 作為開發平臺,原以為只要在控制面板內啟用 php_oci8.dll 與 php_pdo_oci.dll 兩項延伸模組就大公告成,沒想到整臺炸掉了!關於連線 Oracle 資料庫所需的函式套件:
  • 取得 Oracle Instant Client Package (例:instantclient-basic-nt-11.2.0.3.0.zip)
  • 解壓縮後將:oci.dll、ociw32.dll、orannzsbb11.dll、oraociei11.dll 丟到 C:\Windows\System32 目錄下
  • 啟用 php_oci8_11g.dll 與 php_pdo_oci.dll 兩項延伸模組
  • 重新啟動 Apache 應該沒問題了

最後是 PHP-CLI 環境參數


透過瀏覽器檢索,資料可從 Oracle 中讀出並在網頁中顯示。但此次開發最終要丟進排程執行,所以直覺把 PHP script 餵給 PHP-CLI(即php.exe) 處理應該就行了...。沒想到 PHP-CLI 使用另組環境參數運作(炸),暗雷何其多。舉凡任何 oci_* 語法均是未定義:
Fatal error: Call to undefined function oci_connect()
查詢 PHP-CLI 使用的環境參數並進行修正(此例為 php-cli.ini):
C:\UniServerZ\core\php54>php --ini
Configuration File (php.ini) Path: C:\Windows
Loaded Configuration File:         C:\UniServerZ\core\php54\php-cli.ini
Scan for additional .ini files in: (none)
Additional .ini files parsed:      (none)
這邊很明顯,只要在設定內把 extension 補上去就沒問題了。

6月 26, 2013

透過 JDBC 連線 Oracle 資料庫

要透過 Java JDBC 連線至 Oracle 資料庫,有幾個要注意的地方:

首先搞清楚連線對象是 "SID" 或 "Service Name" 因為兩者使用語法並不相同,其中:

1. SID (unique name of the INSTANCE)
jdbc:oracle:thin:[USER/PASSWORD]@[HOST][:PORT]:SID
2. Service Name (Alias to an INSTANCE)
jdbc:oracle:thin:[USER/PASSWORD]@//[HOST][:PORT]/SERVICE
實際例子:
Connection conn = null;
conn = DriverManager.getConnection
       ("jdbc:oracle:thin:ID/PASS//HOST_IP:1521/SERVICE_NAME"); 
再來,包裝你想送出的查詢
String StrX = "SELECT * FROM FOO";
sqlMsg = sqlMsg + "WHERE BAR=15";

Statement myQuery = conn.createStatement();
ResultSet Output = myQuery.executeQuery(sqlMsg);

while( Output.next() ) /* 透過迴圈取得資料 */
{
  System.out.println ( 
    Output.getString(1) + "," + Output.getString(2)+ "," +
    Output.getString(3) + "," + Output.getString(4)
  );
}

Output.close();
myQuery.close();
conn.close();
最後必須有一段程式碼,來處理例外狀況 (Java編譯時會偵測)
catch (ClassNotFoundException e) 
{ 
  System.err.println(e.getMessage()); 
}
catch (SQLException e) 
{ 
  System.err.println(e.getMessage()); 
} 
finally 
{ 
  try 
  { 
    if(conn != null) 
      conn.close(); 
  } 
  catch(SQLException e) 
  { 
    System.err.println(e); 
  } 
} 
--

有關 Java 8 中 java.sql.* 函式庫的變革:
The JDBC 4.2 API includes both the java.sql package, referred to as the JDBC core API, and the javax.sql package, referred to as the JDBC Optional Package API. This complete JDBC API is included in the Java Standard Edition (Java SE), version 7.

Since 1.8 -- new in the JDBC 4.2 API and part of the Java SE platform, version 8
Since 1.7 -- new in the JDBC 4.1 API and part of the Java SE platform, version 7

然後最重要的是從 JDBC 4.0 起,不需透過 Class.forName() 預先註冊 Driver
auto java.sql.Driver discovery - no longer need to load a java.sql.Driver class via Class.forName
編譯與執行 (工作目錄 c:\project)
> 編譯 javac foo.java
> 執行 java -cp "c:\project;c:\project\ojdbc8\ojdbc8.jar" foo

6月 25, 2013

大型範例資料庫 (供練習 SQL 語法使用)


http://dev.mysql.com/doc/index-other.html

由 MySQL 提供的大型範例資料庫(Sample Database),可拿來練習 SQL 語法。

以 "Employees database" 這個資料庫為例

# mysql -u root -p
mysql> source employees.sql

7月 29, 2011

XML XQuery DOM

[ XML, eXtensible Markup Language ]

一個容易理解閱讀,同時也能讓電腦進行解析辨識的語言。

整個XML文件可以視為一個樹狀結構的文件,文件實體(document entity)視為根節點
加上其他的宣告與標籤稱之為此XML文件的物質結構(Physical Structures),其中須
注意其根節點與根標籤是不同的。

XML的前身是SGML,但是SGML是一種非常嚴謹的檔案描述法,導致過於龐大複雜,
難以理解和學習,進而影響其推廣與應用。

專家們使用SGML精簡製作,並依照HTML的發展經驗,產生出一套使用上規則嚴謹,
但是簡單的描述資料語言:XML

XML被廣泛用來作為跨平台之間互動數據的形式,主要針對數據的內容。
XML設計用來傳送及攜帶資料資訊,不用來表現或展示資料,HTML語言則用來表現資料,
所以XML用途的焦點是它說明資料是什麼,以及攜帶資料資訊。

[ XHTML, eXtensible HyperText Markup Language ]

表現方式與超本文標記語言(HTML)類似,不過語法上更加嚴格。
HTML語法要求比較鬆散,這樣對網頁編寫者較方便,但對於機器來說,語言的語
法越鬆散,處理起來就越困難。

XHTML是一個基於XML的置標語言,看起來與HTML有些相象,本質上說,
XHTML是一個過渡技術,結合了XML(有幾分)的強大功能及HTML(大多數)的簡單特性。
XHTML 就是一種XML應用。它採用XML的DTD文件格式定義


當XML越來越成為一種趨勢,就出現了這樣一個問題:
「如果我們有了XML,我們是否依然需要HTML?」

結論是:需要。因為大量的人們已經習慣使用HTML來作為他們的設計語言。
而 XHTML是一種為適應XML而重新改造的HTML。

XHTML 解決HTML語言所存在的嚴重制約其發展的問題:
HTML 發展到今天存在三個主要缺點:
1. 不能適應現下越多的網路設備和應用的需要,比如手機、PDA。
2. 由於HTML代碼不規範,瀏覽器需要足夠智能和龐大才能夠正確顯示。
3. 數據與表現混雜,這樣你的頁面要改變顯示,就必須重新製作HTML

XHTML的優點是,嚴謹:
當前網路上的 HTML 的糟糕情況讓人震驚,早期的瀏覽器接受私有的HTML標籤,
所以人們在頁面設計完畢后必須使用各種瀏覽器來檢測頁面,看是否兼容。



[ XML DOM , Document Object Models ]

XML DOM 是用於獲取、更改、添加或刪除 XML 元素的標準。
DOM 讓您以程式設計方式讀取、操作和修改 XML 文件。
XML 文檔中的每個成分都是一個節點。

[XQuery]

XQuery 相對於 XML,等同於 SQL 相對於數據庫。XQuery 被設計用來查詢 XML 數據。
XQuery 是用來從 XML 文件找尋、提取元素及屬性的語言。

<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>

doc("books.xml") ... 用於打開 "books.xml" 文件

XQuery 使用 XPath 來選取 XML 文檔中的節點或節點集。

下面的路徑表達式用於在 "books.xml" 文件中選取所有的 title 元素:
doc("books.xml")/bookstore/book/title ,執行結果:

<title lang="en">Everyday Italian</title>
<title lang="en">Learning XML</title>

在 XQuery 中提供了 FLWOR 語法,讓查詢功能更強大

FLWOR 是 "For, Let, Where, Order by, Return" 字母縮寫。

for $x in doc("books.xml")/bookstore/book
where $x/price>30
order by $x/title
return $x/title

for 語句把 bookstore 元素下的所有 book 元素提取到名為 $x 的變量中。
where 語句選取了 price 元素值大於 30 的 book 元素。
order by 語句定義了排序次序。將根據 title 元素進行排序。
return 語句規定返回什麼內容。在此返回的是 title 元素。
let 針對特定反覆運算的給定變數指派值 (此例中未用到)

6月 16, 2011

XML XQuery DOM

[ XML, eXtensible Markup Language ]

一個容易理解閱讀,同時也能讓電腦進行解析辨識的語言。

整個XML文件可以視為一個樹狀結構的文件,文件實體(document entity)視為根節點
加上其他的宣告與標籤稱之為此XML文件的物質結構(Physical Structures),其中須
注意其根節點與根標籤是不同的。

XML的前身是SGML,但是SGML是一種非常嚴謹的檔案描述法,導致過於龐大複雜,
難以理解和學習,進而影響其推廣與應用。

專家們使用SGML精簡製作,並依照HTML的發展經驗,產生出一套使用上規則嚴謹,
但是簡單的描述資料語言:XML

XML被廣泛用來作為跨平台之間互動數據的形式,主要針對數據的內容。
XML設計用來傳送及攜帶資料資訊,不用來表現或展示資料,HTML語言則用來表現資料,
所以XML用途的焦點是它說明資料是什麼,以及攜帶資料資訊。

[ XHTML, eXtensible HyperText Markup Language ]

表現方式與超本文標記語言(HTML)類似,不過語法上更加嚴格。
HTML語法要求比較鬆散,這樣對網頁編寫者較方便,但對於機器來說,語言的語
法越鬆散,處理起來就越困難。

XHTML是一個基於XML的置標語言,看起來與HTML有些相象,本質上說,
XHTML是一個過渡技術,結合了XML(有幾分)的強大功能及HTML(大多數)的簡單特性。
XHTML 就是一種XML應用。它採用XML的DTD文件格式定義

當XML越來越成為一種趨勢,就出現了這樣一個問題:
「如果我們有了XML,我們是否依然需要HTML?」

結論是:需要。因為大量的人們已經習慣使用HTML來作為他們的設計語言。
而 XHTML是一種為適應XML而重新改造的HTML。

XHTML 解決HTML語言所存在的嚴重制約其發展的問題:
HTML 發展到今天存在三個主要缺點:
1. 不能適應現下越多的網路設備和應用的需要,比如手機、PDA。
2. 由於HTML代碼不規範,瀏覽器需要足夠智能和龐大才能夠正確顯示。
3. 數據與表現混雜,這樣你的頁面要改變顯示,就必須重新製作HTML

XHTML的優點是,嚴謹:
當前網路上的 HTML 的糟糕情況讓人震驚,早期的瀏覽器接受私有的HTML標籤,
所以人們在頁面設計完畢后必須使用各種瀏覽器來檢測頁面,看是否兼容。

[ XML DOM , Document Object Models ]

XML DOM 是用於獲取、更改、添加或刪除 XML 元素的標準。
DOM 讓您以程式設計方式讀取、操作和修改 XML 文件。
XML 文檔中的每個成分都是一個節點。

[XQuery]

XQuery 相對於 XML,等同於 SQL 相對於數據庫。XQuery 被設計用來查詢 XML 數據。
XQuery 是用來從 XML 文件找尋、提取元素及屬性的語言。

<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
<author>Giada De Laurentiis</author>
<year>2005</year>
<price>30.00</price>
</book>
<book category="WEB">
<title lang="en">Learning XML</title>
<author>Erik T. Ray</author>
<year>2003</year>
<price>39.95</price>
</book>
</bookstore>

doc("books.xml") ... 用於打開 "books.xml" 文件

XQuery 使用 XPath 來選取 XML 文檔中的節點或節點集。

下面的路徑表達式用於在 "books.xml" 文件中選取所有的 title 元素:
doc("books.xml")/bookstore/book/title ,執行結果:

<title lang="en">Everyday Italian</title>
<title lang="en">Learning XML</title>

在 XQuery 中提供了 FLWOR 語法,讓查詢功能更強大

FLWOR 是 "For, Let, Where, Order by, Return" 字母縮寫。

for $x in doc("books.xml")/bookstore/book
where $x/price>30
order by $x/title
return $x/title

for 語句把 bookstore 元素下的所有 book 元素提取到名為 $x 的變量中。
where 語句選取了 price 元素值大於 30 的 book 元素。
order by 語句定義了排序次序。將根據 title 元素進行排序。
return 語句規定返回什麼內容。在此返回的是 title 元素。
let 針對特定反覆運算的給定變數指派值 (此例中未用到)

6月 01, 2011

並行控制技術 (鎖定/Timestamp)

[ 並行控制技術 ]

1. 鎖定(Locking)
二元鎖定:不為可序列化、活死結、飢餓
互斥鎖定(讀寫鎖定):不為可序列化、活死結、飢餓
二階段鎖定(2PL):分一般、嚴格、保守;可序列化、死結

2. 時戳同步(Timestamp)
可序列化、沒有死結、會有飢餓。
飢餓可用 wait die / wound wait 解。

3. 樂觀同步
可序列化、假設所有交易均可順利執行,交易時
不做檢查。資料暫存在 Local Copy 交易完才檢查。

4. 多重版本
可序列化、以時間為基礎,每次進行資料修改時,
均保留原值。並行執行時,會自動選擇適當的值。

1月 26, 2011

資料倉儲 (Data Warehouse)

資料倉儲(Data Warehouse, DW)

傳統的 DB 主要是用來記錄交易記錄,沒辦法支援即時性的決策,
所以跟決策相關的資訊,都散布在不同的 DB 之中,在這樣的狀況
下常會有資料不一致、重複、無法整合等問題。而且由於沒有過往
的歷史資料,沒法進行趨勢分析(因為DB 多半只存放短期資料)。

所以 Data Warehouse 才因此產生,其特性有四個:

1. 主題導向 (Subject Oriented)
所存的資料是以主題導向(例如銷售、營收),非如傳統 DB 只用來
支援交易流程(例如採購、付款)。

2. 資料整合性 (Integrated)
DW 的設計在於支援多維度的決策,需要廣度、深度兼具,所以會是
一個整合企業內外、不同時間、不同來源的各種資料。這些資料原本
是散落在各 DB 之中的。

3. 資料不變動性 (Non-volatile)
在 DW 的每筆資料,一旦存進去之後,就不能再更改,只供查詢。
只會定期新增資料以供查詢。

4. 資料具有時間差異性 (Time variant)
DW 會存放不同時間(5~10年)的歷史資料,以供趨勢分析、預測。
但是 DB 通常只會儲存某個時間點的資料。

5. 資料一致性
因為 DW 蒐集來自各 DB 的資料,其格式與單位,均不相同。要建立
一個良好的 DW 就是要把這些不同來源的資料,經過整理篩選後才將
資料存入。

資料在存入 DW 之前,要先進行 ETL(萃取 轉換 載入)
萃取(Extract) - 將原始資料從各DB、OLTP、TPS、檔案中取出
轉換(Transform) - 轉換資料格式,使資料可以合乎 DW 的標準
載入(Load) - 將資料載到 DW 中。

CRM DB --+ +-- Data Mart | OLAP
SCM DB --+ + |
OLTP DB --+-> ETL -> DW --+ Data Mart | DSS EIS
TPS DB --+ + |
外來資料--+ +-- Data Mart | EIP

[ 資料超市 Data Mart ]

較小的資料,從 Data Warehouse 中複製出部份集合,專門用來支援特定部門、特定地區、使用者,Data Warehouse 可以視需求適時複製出多份 Data Mart。像是會計用的 Mart,以某個更局部的主題為導向。
優點:導入期較短、成本也比較低,可以快速建立。

[ 線上即時分析 OLAP ]

主要架構在 Data Warehouse 上,提供多角度、多維度的分析,提供決策用途,內建許多分析程式,在傳統的 DB 中,要提供這些分析報告,要用大量的 SQL 查詢,而 OLAP 有 UI 可讓使用者自己決定分析維度。

1. 切片 (Slice)
將資料視為一個立方體,將三維資料切片,固定單一維度。
例如固定時間在 2011年,觀察 (通路 銷量) 二個維度。

2. 切丁 (Dice)
提供縮小範圍檢視,仍維持原有維度。

3. 下拉 (Drill Down)
從原本宏觀的角度,拉到微觀角度。

4. 上轉 (Roll Up)
從微觀拉遠變成宏觀。

5. 旋轉 (Rotation)
也稱為樞扭,不同管理者所在意的觀點不同。

[ 線上即時交易 OLTP ]

使用電腦進行交易的即時處理,在線上發生的交易資料,立刻用電腦
處理資料的輸入作業。舊有的 TPS 較偏向批次作業,而 OLTP 在此
進行改良,結合 DB/網路可以應付資料量大、交易頻繁的情境上。
交易發生的同時,就能同步更新相關資訊。特色有:

1. 基礎作業處理,支援操作階層
2. 使用者為一般職員
3. 資料即時處理

1月 03, 2011

SQL - NOT EXIST usage

網上有一些關於EXISTS 說明的例子,但都說的不是很詳細.比如對於著名的供貨商數據庫,查詢:找出供應所有零件的供應商的供應商名,對於這個查詢,網上一些關於EXISTS的說明文章都不能講清楚.

我先解釋本文所用的數據庫例子,'供貨商' 數據庫,共3個表. 供貨商表 S(S#,SNAME), 貨物表 P(P#,PNAME), 供貨商-貨物表 SP(S#,P#). 字段S#,P#分別代表供貨商和貨物的ID.

在C.J.Date的數據庫系統導論第八版中文版第147頁給出了, EXISTS的比較正規的解釋, "EXISTS( SELECT ... FROM ...)取真值,當且僅當 SELECT ... FROM ... 取非空值.在作為相關子查詢的例子中,SQL涉及子查詢,因此它包含了一範圍變量的引用,即隱式範圍變量S, 它在外查詢中定義."

我個人認為,此處所指的外查詢定義的隱式範圍變量S, 可以用另外一種方法來解釋: 將外查詢表的每一行,代入內查詢作為檢驗, 如果內查詢返回的結果取非空值,則EXISTS子句返回TRUE, 這一行行可作為外查詢的結果行, 否則不能作為結果.

至此可以明確,EXISTS(包括 NOT EXISTS )子句的返回值是一個BOOL值. EXISTS內部有一個子查詢語句(SELECT ... FROM...), 我將其稱為EXIST的內查詢語句.其內查詢語句返回一個結果集. EXISTS子句根據其內查詢語句的結果集空或者非空,返回一個布爾值.

舉一例子說明: 找出供應所有零件的供應商的供應商名

SELECT DISTINCT S.SNAME
FROM S
WHERE NOT EXISTS
(
SELECT *
FROM P
WHERE NOT EXISTS
(
SELECT *
FROM SP
WHERE SP.S#=S.S#
AND SP.P#=P.P#) );

假設數據如下:

S
S# SNAME
1 S1
2 S2

P
P# PNAME
1 P1
2 P2

SP
S# P#
1 1
1 2
2 1

這個查詢過程如下:

STEP1: 將S表第一行(1,S1) 作為隱式變量V1, 代入第一個NOT EXISTS子句. 由於這個子句嵌套一個NOT EXISTS子句, 再將 P表第一行(1,P1) 作為隱式變量V2, 和V1一起代入第二個NOT EXISTS子句中, 這時第二個NOT EXISTS的內查詢子句變成

SELECT *
FROM SP
WHERE SP.S#=1
AND SP.P#=1

其返回結果集為

S# P#
1 1

這個返回結果集非空,注意NOT EXISTS子句返回的是EXISTS子句的非,因此 第二個NOT EXISTS 子句返回FALSE. 因此V2不能加入第一個NOT EXISTS子句的內查詢子句返回結果.

同理,將P表第二行(2,P2)作為隱式變量V3, 與V1一起代入第二個NOT EXISTS子句中,內查詢返回結果集非空(返回 行(1,2) ), 因此V3也不能加入第一個NOT EXISTS子句的內查詢返回結果集.

至此, 對於隱式變量V1(也就是S的第一行), P表的每一行都已代入第二個NOT EXISTS子句中進行檢驗,返回結果是一個空集, 因此對於第一個NOT EXISTS子句,其內查詢子句返回結果為空.因此,第一個NOT EXISTS子句返回TRUE.因此, V1(1,S1)加入外查詢的結果集.

STEP 2: 將S表的第二行(2,S2)作為隱式變量 V4, 代入第一個 NOT EXISTS 子句. 將 V4,V2, 一起代入第二個NOT EXISTS子句. 第二個NOT EXISTS子句內查詢結果集返回非空(2,1),第二個NOT EXISTS子句返回FALSE.V2 不能加入第一個NOT EXISTS子句的內查詢結果集.

將V4,V3 一起代入第二個NOT EXISTS子句, 這時第二個NOT EXISTS子句的內查詢子句變成:

SELECT *
FROM SP
WHERE SP.S#=2
AND SP.P#=2

在SP表中,並沒有S#=2 AND P#=2 的一行,因此,第二個NOT EXISTS子句的內查詢子句返回空集,第二個NOT EXISTS子句返回 TRUE. 因此V3, 可以插入第一個NOT EXISTS子查詢結果集.

至此, 對於隱式變量V4(也就是S的第2行), P表的每一行都已代入第二個NOT EXISTS子句中進行檢驗.第一個NOT EXISTS子查詢語句返回結果集為:

P# PNAME
2 P2

非空,因此第一個NOT EXISTS子句返回false,V4(2,S2) 不能加入外查詢的結果集.

至此S表的每一行都代入第一個NOT EXISTS子句中進行檢驗, 外查詢的返回結果是

SNAME
S1

查詢結束.

從上述查詢過程來可以得知, 第二個NOT EXISTS子句的內查詢語句返回的結果集的含義是, 一個供貨商能否供應某種貨物. 第一個NOT EXISTS的內查詢語句返回的結果集的含義是, 某一個供貨商不能供應的貨物. 而連起來使用,就是用排除法得到"沒有不能供應的貨物的供貨商", 也就是能供應所有貨物的供貨商.

12月 15, 2010

交易處理

ACID、並行控制、Commit、Check point、Roll Back

教的很詳細

投影片連結

11月 19, 2010

不一致分析



證明 2PL 保證可序列化性質

pf:
(若 p 則 q ≡ 若 ~q 則 ~p )
使用反證法,假設排程可序列化。
表示存在一組 cycle (T1 -> T2 ->...-> Tn -> T1)
在上式中表示,當 T1 完成工作後,會進行 Unlock 動作放出資源;
而 T2 要開始交易前,會進行 Lock 動作鎖住資源。因此可以條列成

---
T1 Unlock 之後,T2 進行 Lock (即 Unlock 1 -> Lock 2)
T2 Unlock 之後,T3 進行 Lock (即 Unlock 2 -> Lock 3)
...
Tn Unlock 之後,T1 進行 Lock (即 Unlock n -> Lock 1)
---

為了達成 2PL,所有交易的 Lock 都要在 Unlock 之前,即 Lock(x) -> Unlock(x)。
但是在上式中,可以發現 Unlock 1 發生在最開頭,而 Lock 1 發生在最後面。
此點無法滿足 2PL。

11月 03, 2010

SQL 快攻手冊

# (DDL) 針對 Table 架構運作的指令 - CREATE / DROP / ALTER
# (DML) 針對 值組 運作的指令 - INSERT / DELETE / UPDATE

# 建立一張表內含兩個欄位
create table myTab
(sn char(10),
name char(10)
)

# 在 myTab 加入一筆資料
INSERT INTO myTab
VALUES ('1', 'jack');

# 在 myTab 中異動加入一個新的欄位 tel
alter table myTab
add tel char(20);

11月 02, 2010

關聯式計算 (Relational Calculus)

[關聯式計算] 分為二類:值組導向與定義域導向

員工(編號, 姓名, 電話, 薪水, 年紀)

ex: 找出年紀大於 30 的員工列出編號名字
ans: { e.編號 , e.名字 | 員工(e) and e.age>30 }

中譯: 在員工表中的每個 值組(tuple) 命名為 變數e 來操作

要找年紀大於30者,就直接給條件 e.age>30 就可以了

12月 23, 2009

[DB] Transaction & Isolation Level

相關文件參考:wikipedia

在資料庫系統中,交易(Transaction)是指一連串不可分割的操作程序,如果在這之中的任一步驟失敗,那麼資料狀態就要回復(Rollback)到尚未異動前的狀態才可行,交易順利完成稱之為 Commit。

為了要維持資料庫的一致、正確性,一個 Transaction 要包含四個(ACID)特性:

(1) Atomicity
一個 Transaction 不可被分割,正常執行完成就宣告 Commit 表示交易正常結束;反之則用 Rollback 宣告交易失敗,資料要回復到異動前的狀態。
(2) Consistency
每筆交易所異動到的資料,要滿足資料庫整體資料的一致性。
(3) Isolation
每筆交易間應當是獨立的,當一筆交易尚未處理完時,異動的資料不能被其他交易使用,避免異動的結果造成其他交易的不正確。
(4) Durability
交易所異動的資料,只有當交易 Commit 後,才會將異動部份更新到資料庫內,即使系統發生故障,也不會影響異動後的資料。

針對 Isolation 的部份,可區分為四個層級。在詳述這些層級之前,先列出同時有多個交易存取資料時,會發生的錯誤:
* Dirty Read
亦稱為 READ UNCOMMITTED,一個交易尚未完成,其他筆交易讀取同一筆資料,可能因為前一個交易對資料有所異動,造成後來的交易讀到錯值。
* Nonrepeatable Read
一個交易對同筆資料進行兩次以上的讀取,但是結果卻不相同,因為在讀取的中間,其他交易有異動過資料,所以造成錯誤。
* Phantoms Read
交易使用 WHERE 指定資料的選取範圍(Range),可能因為其他交易對資料的異動,讓原先不在範圍內的資料,也一併被選中。

將 Isolation 分為四個層級:
[ Read Uncommitted ]
此一等級限制最少,允許讀取其他 Transaction 尚未 Commit 的資料,無法確保資料的一致性及完整性。
[ Read Committed ]
不允許讀取正在「異動」的資料;當資料正由一個 Transaction 異動時,就不允許其他人讀取該資料;但對於一個進行中的 Transaction 允許其他 Transaction 可以更改相關資料。
[ Repeatable Read ]
當一筆資料被讀取後,其他的 Transaction 就不允許修改(UPDATE)或刪除(DELETE)該筆資料,這意味著,在此條件下:同樣的 SQL 語法會得到相同的結果。
[ Serialized Read ]
當一筆資料被讀取後,其他的 Transaction 不允許新增(Insert)、修改、刪除資料。這表示 SQL 的查詢結果,不會因為另一筆 Transaction 新增了一筆符合選取範圍的資料,造成兩次查詢結果的不同。


Isolation Level / Lost Dirty Nonrepeatble Phantoms
可能發生的錯誤 Update Ready Read Read
--------------------------------------------------------
Read Uncommitted V V V V
Read Committed V V
Repeatable Read V
Serialized Read