2014-09-25 114 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''),三引号字符串(""")等的支持,使得这类事情要容易得多。

相关问题