2012-03-21 91 views
-1

我正在开发应该与数据库一起工作的python应用程序。我遇到了一个问题。在PHP我可以直接只需$符号变量的查询,但在python我写这段代码:蟒蛇PHP像字符串连接

query = "INSERT INTO shops (id, shop_id, shop_url, shop_name, shop_cat, datas)" + "VALUES("+count+", "+str(shop_id)+", "+shop_url+", "+shop_name+", "+shop_cat+", "+pdfs+datas+");" 

是否有任何PHP做类似的方法,我的意思是做一个字符串里面?

+0

你应该真的使用DB API和那些替代你的方法。以这种方式构建字符串是SQL注入攻击的沃土。 – Keith 2012-03-21 10:40:08

+0

你在找什么被称为[字符串插值](http://stackoverflow.com/search?q=python+string+interpolation) – georg 2012-03-21 10:47:18

回答

3

你应该从来没有连接一个SQL字符串。您正在询问SQL注入。

使用内置的DB API逃脱:

cursor.execute("INSERT INTO shops (id, shop_id, shop_url, shop_name, shop_cat, datas) VALUES (%d, %s, %s, %s, %s, %s)", (count, show_id, shop_url, shop_name, shop_cat, pdfs + datas)) 

......和您的查询将被正确转义。

通常在Python中,可以使用“+”连接字符串。你也可以使用类似printf的语法“Hello%s!” %“World”和更新的格式化语法“Hello {0}”。格式('World!')

+0

我使用sqlite3,但它给出了错误:cursor.execute(“INSERT INTO shops (id)VALUES(%d)“,(id)) sqlite3.OperationalError:接近”%“:语法错误 – user873286 2012-03-21 11:20:06

+0

Ahh。不同数据库使用不同的占位符。 Sqlite使用'?',所以用%替换%d和%s。 http://docs.python.org/library/sqlite3.html – Gurgeh 2012-03-21 12:51:30

+0

另外“(id)”不是在Python中制作一个元素的元组的正确方法。使用“(id,)”。此外,“id”是一个不好的变量名称,因为它隐藏了一个名为id的内建函数,但这更多的是风格问题。 – Gurgeh 2012-03-21 13:17:55

0

如何使用格式:

query = (
    "INSERT INTO shops (id, shop_id, shop_url, shop_name, shop_cat, datas)" 
    "VALUES(%d, %s, %s, %s, %s, %s%s);" % 
    (count, show_id, shop_url, shop_name, shop_cat, pdfs, datas)) 

或者这样:

query = (
    "INSERT INTO shops (id, shop_id, shop_url, shop_name, shop_cat, datas)" 
    "VALUES(%(count)d, %(show_id)s, %(shop_url)s, %(shop_name)s," 
    " %(shop_cat)s, %(pdfs)s%(datas)s);" % vars()) 
0

不要创建通过这样的字符串连接查询,使用paramterize这样的查询

cursor.execute(""INSERT INTO shops (id, shop_id, shop_url, shop_name, shop_cat, datas) VALUES(?,?,?,?,?,?)", (count, shop_id, shop_url, shop_name, shop_cat, datas)) 

这样可以避免长时间的麻烦,而且运行速度也更快。 VALUES后的符号?可以

1

不能直接不同的API之间有所不同,但你可以使用string formating operations

query = "...VALUES(%d, %d, %s, %s)" % (some_int, some_other_int, some_string, some_other_string) 

在你的情况,这不过是一个坏主意。对于这样的事情在SQL查询,你应该这样做,而不是:

query = "INSERT INTO ... VALUES(?, ?, ?, ?)" 
cursor.execute(query, some_int, some_other_int, some_string, some_other_string) 

这是为了对抗SQL注入安全的最简单,最有效的方法。 所有主要的SQL Python模块(至少MySQL,SQLite,PostgreSQL)都支持此语法。

关于这个的更多细节在sqlite3 module doc

0

首先,以这种方式构造SQL查询是一种可怕的做法。您应该使用参数化查询。现在,Python的DB-API 2.0 (PEP-249)定义几个PARAM风格:

paramstyle

 String constant stating the type of parameter marker 
     formatting expected by the interface. Possible values are 
     [2]: 

      'qmark'   Question mark style, 
          e.g. '...WHERE name=?' 
      'numeric'  Numeric, positional style, 
          e.g. '...WHERE name=:1' 
      'named'   Named style, 
          e.g. '...WHERE name=:name' 
      'format'  ANSI C printf format codes, 
          e.g. '...WHERE name=%s' 
      'pyformat'  Python extended format codes, 
          e.g. '...WHERE name=%(name)s' 

例如MySQL的默认PARAM风格是 “格式”(这是C风格的),这样你会做

cursor.execute("INSERT INTO shops (id, shop_id, shop_url, shop_name, shop_cat, datas) VALUES (%s, %s, %s, %s, %s, %s)" , (count, shop_id, shop_url, shop_name, shop_cat, pdfs+datas) 
0

第一所有,不要创建SQL查询。也就是说,这是如何在Python中获得命名(PHP风格)变量插值。

使用string template。这里是一个例子:

from string import Template 

foo = Template('All that $does is $metal.') 
bar = foo.substitute(does='glitters', metal='gold') 

print(bar) // All that glitters is gold.