2014-09-25 112 views
0

我試圖在psql中插入以下數據,並顯示出我奇怪的錯誤。在將用戶名和密碼插入數據庫時​​出錯

 -bash-4.1$ psql -t -d mydb -c 'insert into ftp_mgr (id, info) values("192.168.1.12",  '{"username": "Administrator", "password": "abc456$", "serverAddr":"192.168.1.12"}');' 

     psql: warning: extra command-line argument "password:" ignored 
     psql: warning: extra command-line argument "abc456$," ignored 
     psql: warning: extra command-line argument "serverAddr:192.168.1.12});" ignored 
     psql: FATAL: role "Administrator," does not exist 

回答

0

這與PostgreSQL無關。這是一個shell引用問題。

不能在bash中嵌套單引號。所以這個:

'insert into ftp_mgr (id, info) values("192.168.1.12",  '{"username": "Administrator", "password": "abc456$", "serverAddr":"192.168.1.12"}');' 

被讀到:

'insert ...'{ 

{是*不帶引號的字符串的一部分。因此,shell試圖將{"username": "Administrator", "password": "abc456$", "serverAddr":"192.168.1.12"}解釋爲shell命令。


在這裏做最簡單的就是用一個帶引號的here文檔,以避免需要處理'字面報價與外殼的引用混合:各地這裏 -

psql -t -d mydb <<'__END__' 
insert into ftp_mgr (id, info) values 
("192.168.1.12", '{"username": "Administrator", "password": "abc456$", "serverAddr":"192.168.1.12"}'); 
__END__ 

的報價文件標籤是重要。如果將它們排除在外,bash仍會查找並替換$variable字符串等。這可以非常方便,但在這種情況下顯然不是你想要的。


如果您必須使用-c做到這一點,你有兩個選擇:

使用shell的字符串連接。無論何時你想要一個單引號,結束當前單引號字符串,寫"'",並打開一個新的單引號字符串。所以你會寫:

'insert ... values(..., '"'"'{".... 

混淆閱讀,不是嗎?第一個'結束單引號外殼字符串。然後"'"是一個單引號,用shell引用的雙引號引用。然後下一個'開始一個新的單引號字符串。

這是可怕的閱讀,而且它也不遑多讓寫爲:

'insert ... values(..., '\''{".... 

所以個人,當我需要一個參數字符串中的單引號,我不是雙引號將整個字符串和反斜槓轉義shell字符:

"insert into ftp_mgr (id, info) values(\"192.168.1.12\", '{\"username\": \"Administrator\", \"password\": \"abc456\$\", \"serverAddr\":\"192.168.1.12\"}');" 

......或者在可能的情況下,我使用引用此處的文檔來解決整個可怕的混亂。


我的首選是避免使用這種類型的shell並使用簡單的Python腳本。

import psycopg2 
conn = psycopg2.connect('dbname=postgres') 
curs = conn.cursor() 
curs.execute(r'insert into ftp_mgr (id, info) values(%s, %s);', (
    r'192.168.1.12', 
    r'{"username": "Administrator", "password": "abc456$", "serverAddr":"192.168.1.12"}' 
    )) 

Python對原始字符串(r''),三引號字符串(""")等的支持,使得這類事情要容易得多。

相關問題