2017年11月13日 星期一

Python cx_Oracle

Python cx_Oracle

安裝cx_Oracle

dll 找不到指定程序

過程一波三折,建議作法是,先不要聽網路上的八卦,把所有cx_Oracle移除,然後把依著網路八卦複製什麼檔到那裡的檔案通通砍了!
然後至官網下載對應的版本(作業系統、資料庫版本)之後,就可以直接安裝!!
是的,我弄了四個多小時就是這樣子做就好了!
不過對於oracle的設置確認還是要先處理好!

tnsping 可以測試是否設置正常

import cx_Oracle

沒有錯誤訊息的時候眼淚都流出來了!

連線oracle

MIS2000老師有教過,連接資料庫四步驟!
CONNECTION->SQLCOMMAND->SQLREADER->CLOSE(有借記得要有還)

db = cx_Oracle.connect(帳號, 密碼, 連接的資料庫)
db.version


眼淚再次的噴發!看到版本了!

一般來說,如果直接透過cx_Oracle.cursor.excute來取得資料集的話,這個回傳資料集會是一個物件!

cursor = db.Cursor()
sql = 'select 123 coluu from dual'
cursor.excute(sql)

當然這要看實際的應用是不是有要保留這個物件,有的話就可以配合pickle來將檔案序列化(我是這樣想@@)
不過如果要做直接使用的話,也可以搭配pandas

pandas

import pandas as pd
df = pd.read_sql(sql, db)

就可以開始做後續的利用了!
不過別忘了,有借有還!

db.close()

cx_oracle query

官方git sample

import cx_Oracle
db = cx_Oracle.connect(帳號, 密碼, 連接的資料庫)
sql = 'select 123 coluu from dual union select 456 coluu from dual'
cursor = db.Cursor()

一次取一筆:fetchone

每執行一次,指標就會往下一筆過去

cursor.execute(sql)
#  取回第一筆
row = cursor.fetchone()
print(row)
#  取回第二筆
row = cursor.fetchone()
print(row)

結果如下:

>>>cursor.fetchone()
(123,)
>>>cursor.fetchone()
(456,)

一次取多筆:fetchmany

透過numRows指定一次取回的筆數

cursor.execute(sql)
res = cursor.fetchmany(numRows=3)

結果如下:

>>>res = cursor.fetchmany(numRows=2)
>>>res
[(123,), (456,)]

一次全取回:fetchall

cursor.execute(sql)
all = cursor.fetchall()

結果如下:

>>>all
[(123,), (456,)]

直接迴圈取回:execute

for cur in cursor.execute(sql):
  print(cur)

結果如下:

(123,)
(456,)

確認影響筆數:rowcount

在執行一個動作之後確認影響筆數
在select的情況下,回傳的不是影響筆數,而是目標游標所在。
這部份很多人誤會了!

cursor.rowcount

結果如下:

2

SQL Statement帶參數

在執行select的時候,帶參數是很正常的需求。
所以where條件上,需要可以依需求來取得資料。

str_sql = "select column from yourTable where col1=:col_a and col2=:col_b"
cursor.execute(str_sql, {col_a: 'your condition', col_b: 'your condition'})

或者也可以將參數先用dict格式裝起來

str_sql = "select column from yourTable where col1=:col_a and col2=:col_b"
dict_con = {'col_a': 'your condition', 'col_b': 'your condition'}
cursor.execute(str_sql, dict_con)

批次寫入資料庫

Oracle官方文件
不少情況在寫入資料庫的時候需求批量處理,簡單的作法上當然是透過迴圈來處理,但是這部份cx_Oracle與oracle都替我們想好了。
透過executemany搭配tuple就可以滿足了。

官方範例

create_table = "
CREATE TABLE python_modules (
module_name VARCHAR2(50) NOT NULL,
file_path VARCHAR2(300) NOT NULL
)
"
from sys import modules
cursor.execute(create_table)
M = []
for m_name, m_info in modules.items():
try:
    M.append((m_name, m_info.__file__))
except AttributeError:
    pass

>>> len(M)
76
>>> cursor.prepare("INSERT INTO python_modules(module_name, file_path) VALUES (:1, :2)")
>>> cursor.executemany(None, M)
>>> db.commit()
>>> r = cursor.execute("SELECT COUNT(*) FROM python_modules")
>>> print cursor.fetchone()
(76,)
>>> cursor.execute("DROP TABLE python_modules PURGE")

重點的部份在於後段的cursor.prepare與cursor.executemany的搭配使用!

str_sql = "select column from yourTable where col1=:col_a and col2=:col_b"
cursor.prepare(str_sql)

dict_con = {'col_a': 'your condition', 'col_b': 'your condition'}
cursor.execute(None, dict_con)

沒有留言:

張貼留言