2013-04-16 143 views
7

我想插入一些二進制數據到BYTEA列中,但我發現Doxygen輸出缺少細節,並且http://pqxx.org/在過去幾天裏一直在關閉。如何使用C++ libpqxx API將二進制數據插入到PostgreSQL BYTEA列中?

我怎麼會去插入somefile.bin的內容到表一列BYTEA?

我有什麼沿着這些路線是:

pqxx::work work(conn); 
work.exec("CREATE TABLE test (name varchar(20), data BYTEA)"); 
work.exec("INSERT INTO test(name, data) VALUES ('foo', <insert filename.bin here>)"); 
work.commit(); 

如果它的確與衆不同,我想使用新的hex格式中的PostgreSQL 9.1提供BYTEA。

回答

9

想通了。這裏是展示如何插入一堆二進制對象到表的例子:

pqxx::connection conn(...); 
conn.prepare("test", "INSERT INTO mytable(name, binfile) VALUES ($1, $2)"); 
pqxx::work work(conn); 
for (...) 
{ 
    std::string name = "foo"; 
    void * bin_data = ...; // obviously do what you need to get the binary data... 
    size_t bin_size = 123; // ...and the size of the binary data 

    pqxx::binarystring blob(bin_data, bin_size); 
    pqxx::result r = work.prepared("test")(name)(blob).exec(); 
} 
work.commit(); 

這裏是如何得到的二進制數據備份出來的數據庫:

pqxx::result result = work.exec("SELECT * FROM mytable"); 
for (const auto &row : result) 
{ 
    pqxx::binarystring blob(row["binfile"]); 
    void * ptr = blob.data(); 
    size_t len = blob.size(); 
    ... 
} 
+0

我喜歡你的解決方案測試,但我不喜歡使用conn.prepare。當我有'n'元素插入一個查詢(性能問題)時,它限制了我。我正在研究解決方案(使用pqxx 5.0.1)。 – LAL

1

沒有pqxx: :通過插入的字符串。我用以下解決方案來做到這一點:

===存儲一wxImage數據庫====

//Getting image string data 
wxImage foto = (...); 
wxMemoryOutputStream stream; 
foto.SaveFile(stream,wxBITMAP_TYPE_PNG); 
wxStreamBuffer* streamBuffer = stream.GetOutputStreamBuffer(); 
size_t tamanho = streamBuffer->GetBufferSize(); 
char* fotoData = reinterpret_cast<char*>(streamBuffer->GetBufferStart()); 
string dados(fotoData, tamanho); 

//Performing the query 
conn->prepare("InsertBinaryData", "INSERT INTO table1(bytea_field) VALUES (decode(encode($1,'HEX'),'HEX'))") ("bytea",pqxx::prepare::treat_binary); 

pqxx::work w = (...); 
w.prepared(dados).exec(); 



===檢索已wxImage從數據庫中=== =

pqxx::result r = w.exec("SELECT bytea_field FROM table1 WHERE (...)"); 
w.commit(); 

const result::tuple row = r[0]; 
const result::field tfoto = row[0]; 

pqxx::binarystring bs(tfoto); 
const char* dadosImg = bs.get(); 
size_t size = bs.length(); 

wxMemoryInputStream stream(dadosImg,size); 
wxImage imagem; 

imagem.LoadFile(stream); 

我希望它是有幫助的。

0

而不是使用準備的SQL語句conn.prepare在斯特凡的答案,如果你想你可以簡單地使用pqxx::escape_binary函數重載之一來轉義二進制數據。 Here是文檔。

0

由於這個問題是通過libpqxx插入BYTEA頂部的搜索結果,這裏是另一種方式來做到這一點使用參數化查詢,這是如果執行單一插入比較合適。

// Assuming pre-existing pqxx::connection c, void * bin_data, size_t bin_size... 
pqxx::work txn(c); 
pqxx::result res = txn.parameterized("INSERT INTO mytable(name, binfile) VALUES ($1, $2)") 
            (name) 
            (pqxx::binarystring(bin_data, bin_size)) 
            .exec(); 
txn.commit(); 

注意,參數應可與quoteesc方法逃脫。

還要注意的是使用pqxx::connection::prepare的接受的答案會導致準備查詢的連接的整個生命週期存在。如果連接持續時間長,並且不再需要準備好的查詢,則可能需要通過調用pqxx::connection::unprepare來刪除該連接。

0

我想出了利用內幕std::string二進制數據的靈活解決方案。

我提出這個新的解決方案,因爲目前的答案是舊的(2013年),我一直在尋找使用pqxx 5.0.1多插入查詢。

通過該解決方案波紋管,你必須使用一個for loop單一插入查詢追加多個二進制數據的靈活性。

CustomStruct data = .... ; // have some binary data 

// initialise connection and declare worker 
pqxx::connection conn = new pqxx::connection(...);  
pqxx::work w(conn); 

// prepare query 
string query += "INSERT INTO table (bytea_field) VALUES (" 
// convert your data in a binary string. 
pqxx::binarystring blob((void *)&(data), data.size()); 
// avoid null character to bug your query string. 
query += "'"+w.esc_raw(blob.str())+"');"; 

//execute query 
pqxx::result rows = w.exec(query); 

當我們想從數據庫中檢索數據,你應該有你的數據類型(CustomStruct例如)的範圍,你應該能夠轉換回在您選擇的二進制格式。

// assuming worker and connection are declared and initialized. 
string query = "SELECT bytea_field FROM table;"; 
pqxx::result rows = w.exec(query); 
for(pqxx::result::iterator col = rows.begin(); col != rows.end(); ++col) 
{ 
    pqxx::binarystring blob(col[0]); 
    CustomStruct *data = (CustomStruct*) blob.data(); 
    ... 
} 

這與pqxx 5.0.1c++11postgresSQL 9.5.8

相關問題