2012年2月29日星期三

直接以PL/SQL印出整潔的表格(table)架構

執行以下SQL指令:


SELECT
user_tab_columns.column_name Column_Name,
user_tab_columns.data_type Format,
NVL2(user_cons_columns.constraint_name, 'YES', '') Primary_Key,
CASE
  WHEN user_tab_columns.nullable='Y' THEN 'NO'
  WHEN user_tab_columns.nullable='N' THEN 'YES'
END Mandatory,
user_tab_columns.table_name
FROM user_cons_columns
LEFT JOIN user_constraints ON (user_cons_columns.constraint_name=user_constraints.constraint_name)
RIGHT OUTER JOIN user_tab_columns ON (user_cons_columns.table_name=user_tab_columns.table_name AND user_cons_columns.column_name=user_tab_columns.column_name AND user_constraints.constraint_type='P')
ORDER BY user_tab_columns.table_name, user_tab_columns.column_id;



若果使用SQL Developer更可以把結果直接儲存作.xls。




改良版(會把字符類別的長度列出)︰

SELECT
user_tab_columns.column_name Column_Name,
CASE
  WHEN user_tab_columns.data_type LIKE '%CHAR%' THEN user_tab_columns.data_type || '(' || user_tab_columns.char_length || ' CHAR)'
  ELSE user_tab_columns.data_type
END Format,
NVL2(user_cons_columns.constraint_name, 'YES', '') Primary_Key,
CASE
  WHEN user_tab_columns.nullable='Y' THEN 'NO'
  WHEN user_tab_columns.nullable='N' THEN 'YES'
END Mandatory,
user_tab_columns.table_name
FROM user_cons_columns
LEFT JOIN user_constraints ON (user_cons_columns.constraint_name=user_constraints.constraint_name)
RIGHT OUTER JOIN user_tab_columns ON (user_cons_columns.table_name=user_tab_columns.table_name AND user_cons_columns.column_name=user_tab_columns.column_name AND user_constraints.constraint_type='P')
ORDER BY user_tab_columns.table_name, user_tab_columns.column_id;

2012年2月27日星期一

把嗶聲關掉

在中文輸入法篇碼輸入錯誤時,會發出嗶(beep)聲,這個很煩人,所以找辦法關掉。

在Arch Linux上,方法很簡單。

使用root權限在/etc/modprobe.d底下建立一個conf檔,例如/etc/modprobe.d/nobeep.conf

內裡加入阻入kernel載入pcspkr的設定句︰blacklist pcspkr

以上動作可以用一句指令完成︰
echo "blacklist pcspkr" > /etc/modprobe.d/nobeep.conf

資料來源︰https://wiki.archlinux.org/index.php/Kernel_modules#Blacklisting

2012年2月22日星期三

Arch Linux開關機時讀取及儲存ALSA音量狀態


首先在/etc/rc.conf內的DAEMONS列加上alsa

修改/etc/conf.d/alsa,將SAVE_VOLUME設為yes,如下︰

SAVE_VOLUME="yes"


完成並重新登入。


若果希望將用戶音量狀態分別儲存,可以額外使用以下方法。

~/.bash_login加上alsactl restore -f ~/.asoundrc
可用以下指令完成︰
echo "alsactl restore -f ~/.asoundrc" >> ~/.bash_login

~/.bash_logout加上alsactl store -f ~/.asoundrc

可用以下指令完成︰
echo "alsactl store -f ~/.asoundrc" >> ~/.bash_login

但若果你的home底下已有.bash_profile.profile任何一個檔案,則建議把alsactl store -f ~/.asoundrc指令加到.bash_profile內。因為當有.bash_profile.profile時,.bash_login便可能不被讀取。

完成並重新登入。

2012年2月12日星期日

在Linux上使用One2Free Lte上網

香港的One2Free電訊公司推出了Lte(4G)的上網服務,並隨服務送上一個Lte的USB modem(ZTE MF820)。使用Linux的我當然是要把這東西攪到能在Linux上能用。


我用的是Arch Linux,所以安裝套件的方法跟RedHat、Debian、Ubuntu、Gentoo等不同,但大家可以用各自的package manager安裝。


步驟︰

因為這類USB modem大多都內置儲存空間以把驅動程式附帶在內,所以在插上USB modem後系統一般都會辨認到USB儲存裝置。這時候,我們就需要用usb_modeswitch工具跳到驅動modem。

安裝libusb及usbutils套件
pacman -S libusb usbutils

安裝usb_modeswitch套件
pacman -S usb_modeswitch


插上USB modem後,使用lsusb指令查看。
lsusb

我的ZTE MF860會顯示一行︰
Bus 004 Device 009: ID 19d2:0166 ONDA Communication S.p.A.

這個就係USB modem上的儲存裝置。

19d2就是其廠商ID
0166是其產品ID

接下來我們要令usb_modeswitch在看到這個ID時自動驅動USB modem,而ZTE MF820的USB modem ID是19d2:0167,至於其他品牌的ID是甚麼就得自己去查了。

/usr/share/usb_modeswitch19d2:0166並修改。
vim /usr/share/usb_modeswitch/19d2:0166

改為以下內容︰

DefaultVendor= 0x19d2
DefaultProduct=0x0166

TargetVendor=  0x19d2
TargetProduct= 0x0167

MessageEndpoint=0x01
MessageContent="55534243e856e2892400000080000685000000240000000000000000000000"

CheckSuccess=20


資料來源︰http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?p=4995

以後插上這個USB modem後,執行lsusb就會看到︰
Bus 004 Device 010: ID 19d2:0167 ONDA Communication S.p.A.

這就代表成功驅動USB modem了。

如果為了令USB modem執行得更有效率,使用root權限啟用option這個module。
modprobe -v option

有些討論提到用option這個module的耗電量和CPU使用率較usb-serial為低。但使用usb-serial則單段TCP連接速度較高。至於如何取捨是否使用option這個module。要是不使用option這個module的話,就不用執行上面的指令了。

如果option module未能辨認您的USB modem,就把ID加到/sys/bus/usb-serial/drivers/option1/new_id
echo -n "19d2 0167" > /sys/bus/usb-serial/drivers/option1/new_id



接下來設定連接到互聯網。

安裝wvdial套件(大家也可以安裝gnome-ppp,但就需要同時安裝gtk2了。)
pacman -S wvdial

安裝後使用root執行︰
wvdialconf

wvdialconf會找到你的USB modem在哪,而且會產生一個/etc/wvdial.conf設定檔案。

執行wvdialconf後大概會看到以下畫面


然後修改/etc/wvdial.conf,改為以下內容︰

[Dialer Defaults]
Init1 = ATZ
Init2 = ATQ0 V1 E1 S0=0 &C1 &D2 +FCLASS=0

# Init command for ZTE 4G modem
#auto (default)
#Init3 = AT+ZSNT=0,0,0
#只使用GPRS
#Init3 = AT+ZSNT=1,0,0
#GPRS優先
#Init3 = AT+ZSNT=0,0,1
#只使用3G
#Init3 = AT+ZSNT=0,0,2
#3G優先
#Init3 = AT+ZSNT=2,0,0
#只使用LTE
Init3 = AT+ZSNT=6,0,0

#LTE優先(此指命經測試並未成功)
#Init3 = AT+ZSNT=0,0,6



Modem Type = Analog Modem
Phone = *99#

ISDN = 0
Password = any
Username = any
Modem = /dev/ttyUSB2
#Baud = 9600
Baud = 460800
Stupid Mode = 1


資料來源︰http://www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?p=4995

使用者帳戶及密碼並無需設定。


然後就可以使用root權限執行wvdial指令連接上網。


大家也可以在wvdial指令後加上&令其改為背景執行。
wvdial &

2012年2月7日星期二

重設Oracle資料庫的序列號(Sequence)

在Oracle資料庫裡要重設序列號(Sequence)並沒有直接的方法,小筆用過的方法也只兩種。一種是先刪除(DROP),再重新建立。這個方法當然不太好,因為當有觸發器(trigger)與其有關連時就不能這麼做了。另一種方法是先把序列號的每次遞增量加大,令序列號在拿下面號碼時就達到最大值,令其自己回復到最小值。但當然這個序列號需要有設為循環(CYCLE)才能這樣做。

第一種方法太簡單,在此不作闡述。第二種方法的具體的方法如下。


假設此序列號的最大值是256,而現時序列已去到100。每次遞增量為1。


ALTER SEQUENCE sequence_name INCREMENT BY 156;  --令序列的遞增量每次為156,那下個序列號就是256了。
SELECT sequence_name.nextval FROM dual;  --令序列號達到下個序列號(256),他就會自己重設了。
ALTER SEQUENCE sequence_name INCREMENT BY 1;  --令序列號的遞增量變回原來的值,這裡假設每次遞增1。

這個方法對其他資料庫物件的影響應該是最小的了。

查看Oracle資料庫表格的外鍵(foreign key)關係

在沒有商業版Toad此類功具的協助下,一般的程式開發者在跟進已完成的系統結構時,遇到文件做得不好的系統,往往都會在追尋從屬關係時感到困難。即使是使用Oracle SQL Developer也未能幫得上忙。

雖然沒有好工具,我們也可以靠Oracle的完善的視圖(View)找查表格(table)之間的關係。

以下是光靠SQL查出關連的外鍵(foreign key),雖然未及使用軟件般有圖表和連線展現關係表,但總算可以清晰地列出有關的外鍵和表格。


代入表格名後,可以找到其他有引用到本表格欄位的外鍵。
SELECT table_name, constraint_name, r_constraint_name, status
FROM user_constraints
WHERE constraint_type = 'R'
AND r_constraint_name in
(
SELECT constraint_name from user_constraints
WHERE constraint_type in ('P', 'U')
AND UPPER(table_name) = UPPER('table_name')
)
ORDER BY table_name, constraint_name;



代入表格名後,可以找到本表格找用了哪些表格欄位作外鍵。
SELECT table_name, constraint_name, r_constraint_name, status
FROM user_constraints
WHERE constraint_type = 'R'
AND UPPER(table_name) = UPPER('table_name')
ORDER BY table_name;



2012年2月6日星期一

停止在Oracle SQL Developer內的替代功能

Oracle SQL Developer有即時替代的功能,只要在執行的SQL語句加上&就可以把某字眼作代入。例子:

SELECT * FROM student WHERE classname = '&classname';

這樣&classname這個字眼可以作為變量,代入不同的值。若先前已定義&classname的話,在執行SQL語句時就會自動代入。若&classname未被定義的話,Oracle SQL Developer會彈出對話框要求即時輸入代入的數值。

這就導致SQL語句不能有&的情況。例子:

SELECT * FROM student WHERE student_name = 'Jr. Sledgehammer & Maul';

因為語句裡有&,令Oracle SQL Developer會彈出對話框詢問取代值。

只要在執行語句之前執行:

SET DEFINE OFF;

Oracle SQL Developer就不會問了。

2012年2月4日星期六

解決一直以來wicd在啟動時不連接eth0的問題

在使用wicd後,一直以來,他都不會在啟動後馬上替我連接eth0的。

但其實,他是有苦衷的。看/var/log/wicd/wicd.log會發現︰

No wired connection present, attempting to autoconnect to wireless network

但原因仍然不明。看ArchWiki後不加思索的就跟著做,在/etc/rc.local裡加上︰

dhcpcd -k eth0
dhcpcd -bn eth0



可以用root權限執行以下指令就不需用vi修改了,

echo "dhcpcd -k eth0" >> /etc/rc.local
echo "dhcpcd -bn eth0" >> /etc/rc.local



2012年2月3日星期五

在Linux上使用QQ

以2009版本以前,Pidginlibpurple一直帶有插件讓大家使用騰訊QQ。可惜騰訊是一家理念奇異的公司。大概也是賺到盡的理念,所以他一直阻攔第三方即時通信軟件使用他們的通信協定,例如是Pidgin。而他們又不在乎Linux的用戶,即使在2010年突然推出了一個能發信息但又未完善的Linux QQ,最後在發佈完1.0 Beta 1就再沒消息,大概已沒有跟進。同時他們又以轉換協定的愚蠢方式(卻又很有效)去阻止第三方客戶端使用。

後來小弟今天發現原來早在2010年就有一小群內地的熱心開發者利用QQ 2010的協定去做了一個Pidgin插件,這個插件還不錯。功能未算完滿,但對比起libpurple的QQ 2008協定插件卻絕對穩定而且來的好。他們的專案存放在Google Code開源—libqq-pidgin

大家可以使用svn下載源最新的原碼自動編譯,又或直接在Downloads頁下載適當的插件版本使用。

最方便的當然是下載已編譯好的插件使用。以下是一個可以供大部分Linux版本使用的方法︰

根據閣下的Linux的版本去選擇下載指令


64位元(x64)︰

wget http://libqq-pidgin.googlecode.com/files/libqq-pidgin.0.71_x64.tar.gz
tar xzf libqq-pidgin.0.71_x64.tar.gz


使用su轉換使用者為root

cp ./libqq.so /usr/lib/purple-2/
chmod 755 /usr/lib/purple-2/libqq.so




32位元(x86)︰

wget http://libqq-pidgin.googlecode.com/files/libqq.so_0.71_i386.7z
7z x libqq.so_0.71_i386.7z
(請確認為有安裝7zip)

使用su轉換使用者為root

cp ./libqq.so /usr/lib/purple-2/
chmod 755 /usr/lib/purple-2/libqq.so



重新啟動Pidgin,就可以在新加帳號內擇選QQ。


是懶人又是使用Arch Linux的話,AUR上有套件包︰
http://aur.archlinux.org/packages.php?ID=49794

使用RedHat/CentOS的懶人可以下載RPM︰http://libqq-pidgin.googlecode.com/files/libqq-0.71-1.x86_64.rpm

在Oracle上限制SELECT的結果列數

在MySQL上,我們可以使用

SELECT student_number, name, class FROM student ORDER BY enrollment_year DESC LIMIT 10, 20;

這樣就可把學生依入學年份排序,並只列出首第11至20個的結果。

Oracle沒有LIMIT,在Oracle上要怎樣做到呢?這問題經常有人在問。

其實我們以用subquery加上ROWNUM的小技巧去做到。

SELECT * FROM (SELECT student_number, name, class FROM student WHERE enrollment_year>2010) WHERE ROWNUM BETWEEN 11 AND 20;

這樣,結果就會例出排序後第11至20個結果。大家亦可以把WHERE clause上改為︰

ROWNUM>10 AND ROWNUM<=20

全句︰

SELECT * FROM (SELECT student_number, name, class FROM student WHERE enrollment_year>2010) WHERE ROWNUM>10 AND ROWNUM<=20;

結果也是一樣的。