2013-11-21 46 views
2

我想要一個插入後觸發器將一個十六進制文本字符串轉換爲其二進制blob等效。sqlite3觸發器將十六進制文本轉換爲二進制blob等效

我已經試過這樣的事情:

CREATE TABLE data 
(
    t_hex TEXT, 
    b_hex BLOB 
); 

CREATE TRIGGER data_insert_trigger AFTER INSERT ON data 
BEGIN 
    UPDATE data SET b_hex = "x''"||t_hex||"''" WHERE rowid = new.rowid; 
END; 

INSERT into data(t_hex) VALUES ('A5A5'); 

這導致:

sqlite> select * from data; 
t_hex = A5A5 
b_hex = x''A5A5'' 

也試過

CREATE TRIGGER data_insert_trigger AFTER INSERT ON data 
BEGIN 
    UPDATE data SET b_hex = x''||t_hex||'' WHERE rowid = new.rowid; 
END; 

這導致:

sqlite> select * from data; 
t_hex = A5A5 
b_hex = A5A5 

任何人都知道利用x'value'語法的方式,但是引用現有的列值或者其他一些基於SQL的機制?

**編輯* *

考慮到自定義功能,感謝CL和LS_dev。 LS_dev提供的SQL解決方案就在我所在的位置。我調整data_t_update_trigger到

CREATE TRIGGER data_t_update_trigger 
AFTER UPDATE ON data 
WHEN NEW.t_hex IS NOT OLD.t_hex 
BEGIN 
    UPDATE data SET b_hex = x'' WHERE ROWID = NEW.ROWID; 
END; 

,併產生我的測試設置:

sqlite> insert into data(t_hex) values('A5A5'); 
sqlite> select t_hex, hex(b_hex) from data; 
A5A5|A5A5 
sqlite> update data set t_hex = 'FF'; 
sqlite> select t_hex, hex(b_hex) from data; 
FF|FF 
sqlite> update data set t_hex = 'FFFE'; 
sqlite> select t_hex, hex(b_hex) from data; 
FFFE|FFFE3F 
sqlite> update data set t_hex = '00'; 
Error: too many levels of trigger recursion 

通過工作,我有資格在data_h_update_trigger一個幾行:

CREATE TRIGGER data_b_update_trigger 
AFTER UPDATE ON data 
WHEN LENGTH(NEW.t_hex)>LENGTH(NEW.b_hex)*2 
BEGIN 
    UPDATE data SET b_hex = NEW.b_hex||COALESCE((
     SELECT b FROM _hb WHERE h=SUBSTR(NEW.t_hex, (LENGTH(NEW.b_hex)*2)+1, 2) 
    ), CAST('?' AS BLOB)) WHERE ROWID = NEW.ROWID; 
END; 

,現在我的測試集的產量:

sqlite> select t_hex, hex(b_hex) from data; 
A5A5|A5A5 
sqlite> update data set t_hex = 'FF'; 
sqlite> select t_hex, hex(b_hex) from data; 
FF|FF 
sqlite> update data set t_hex = 'FFFE'; 
sqlite> select t_hex, hex(b_hex) from data; 
FFFE|FFFE 
sqlite> update data set t_hex = '00'; 
Error: too many levels of trigger recursion 

所以仍然處理一些無法解釋的遞歸。 FWIW,這也正好與這樣的語句:

sqlite> update data set t_hex = 'DEADBEEF'; 
Error: too many levels of trigger recursion 

運行: SQLite的版本3.7.9 2011-11-01○點52分41秒

回答

0

使用用戶定義的函數將會更容易,更便宜,但我得到了一個解決方案。

首先,你需要一個查找表,因爲這:

CREATE TABLE _hb(h TEXT COLLATE NOCASE, b BLOB); 
BEGIN; 
INSERT INTO _hb VALUES('00', x'00'); 
INSERT INTO _hb VALUES('01', x'01'); 
(...) 
INSERT INTO _hb VALUES('A4', x'A4'); 
INSERT INTO _hb VALUES('A5', x'A5'); 
INSERT INTO _hb VALUES('A6', x'A6'); 
(...) 
INSERT INTO _hb VALUES('FE', x'FE'); 
INSERT INTO _hb VALUES('FF', x'FF'); 
COMMIT; 

然後,使recursive triggers(SQLite的> = 3.6。18):

PRAGMA RECURSIVE_TRIGGERS=1; 

可以創建一個觸發器,其將逐漸追加字節b_hex

CREATE TRIGGER data_h_update_trigger 
AFTER UPDATE ON data 
WHEN LENGTH(NEW.t_hex)>LENGTH(NEW.b_hex)*2 
BEGIN 
    UPDATE data SET b_hex = b_hex||COALESCE((
     SELECT b FROM _hb WHERE h=SUBSTR(NEW.t_hex, LENGTH(b_hex)*2+1, 2) 
    ), CAST('?' AS BLOB)) WHERE ROWID = NEW.ROWID; 
END; 

兩個以上觸發器,以觸發對數據插入data_h_update_triggert_hex更新:

CREATE TRIGGER data_insert_trigger 
AFTER INSERT ON data 
BEGIN 
    UPDATE data SET b_hex = x'' WHERE ROWID = NEW.ROWID; 
END; 

CREATE TRIGGER data_t_update_trigger 
AFTER UPDATE OF t_hex ON data 
BEGIN 
    UPDATE data SET b_hex = x'' WHERE ROWID = NEW.ROWID; 
END; 

限制:單步Blob計算限制爲SQLITE_MAX_TRIGGER_DEPTH(默認爲1000)字節。

+0

非常漂亮和密切。將data_t_update_trigger更改爲AFTER UPDATE和s/h_hex/t_hex/g。然後觸摸了data_h_update_trigger中的UPDATE和SELECT。將結果返回頂部。仍然通過一個簡單的更新數據集t_hex ='00'來處理'過多級別的觸發遞歸';和其他類似的陳述。 – maha

+0

是的,我的答案有一些錯別字。如果你運行的觸發器遞歸級別太多,那麼你錯過了'when'子句。對於你在你的問題中發佈回答的問題,我的接受程度是不正確的。我的優點在哪裏? –

+0

獲獎。我會不斷修改實際的工作解決方案並將結果發佈在最前面。感謝您的開始。 – maha

0

Blob literals可以在SQL語句中唯一直接使用;它們不能從SQL代碼動態構建。

要將十六進制字符串轉換爲blob,您必須安裝自己的用戶定義函數。

相關問題