【问题标题】:Python String Formats with SQL Wildcards and LIKE带有 SQL 通配符和 LIKE 的 Python 字符串格式
【发布时间】:2011-03-09 06:15:32
【问题描述】:

我很难让 python 中的一些 sql 正确地通过 MySQLdb。是 pythons 字符串格式让我很生气。

我的 sql 语句使用带通配符的 LIKE 关键字。我在 Python 中尝试了许多不同的东西。问题是,一旦我让其中一个工作起来,MySQLdb 中有一行代码会在字符串格式上打嗝。

尝试 1:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query)

这是不行的。我得到值错误:

ValueError: 索引 128 处不支持的格式字符 ''' (0x27)

尝试 2:

"SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '\%%s\%'" % (查询)

我从尝试 1 中得到相同的结果。

尝试 3:

like = "LIKE '%" + str(query) + "%'" totalq = "SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username " + like

这会正确创建 totalq 变量,但现在当我运行查询时,我从 MySQLdb 收到错误:

文件“build/bdist.macosx-10.6-universal/egg/MySQLdb/cursors.py”,行 158、在执行query = query % db.literal(args) TypeError: not enough 格式字符串的参数

尝试 4:

like = "LIKE '\%" + str(query) + "\%'" totalq = "SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username " + like

这与尝试 3 的输出相同。

这一切看起来真的很奇怪。 python 如何在sql语句中使用通配符?

【问题讨论】:

  • 在下面回显@bernie:来自 psycopg 文档:initd.org/psycopg/docs/…:“永远,永远,永远不要使用 Python 字符串连接 (+) 或字符串参数插值 (%) 将变量传递给 SQL 查询字符串. 甚至在枪口下也没有。”除了 SQL 注入攻击之外,第二个好处是驱动程序“可以自动将 Python 对象与 SQL 文字转换:使用此功能,您的代码将更加健壮和可靠”。这与“组合查询字符串的简单方法,例如使用字符串连接。”

标签: python sql format sql-like


【解决方案1】:

这些查询似乎都容易受到 SQL 注入攻击。

试试这样的方法:

curs.execute("""SELECT tag.userId, count(user.id) as totalRows 
                  FROM user 
            INNER JOIN tag ON user.id = tag.userId 
                 WHERE user.username LIKE %s""", ('%' + query + '%',))

有两个参数传递给execute()

【讨论】:

  • 这看起来也容易受到 SQL 注入的影响。通过用于连接数据库的任何库使用参数化查询是可行的方法。
  • @jrdioko:感谢您的评论。请注意,没有实际的字符串插值,并且查询execute()方法准备的。
  • 我收回这一点,看来语法是相关库执行参数化查询的方式。
【解决方案2】:

这与字符串格式无关,问题在于如何根据 Python 中的数据库操作要求执行查询 (PEP 249)

试试这样的:

sql = "SELECT column FROM table WHERE col1=%s AND col2=%s" 
params = (col1_value, col2_value)
cursor.execute(sql, params)

here are some examples for psycog2 那里有一些解释也应该对 mysql 有效(mysqldb 也遵循 PEP249 dba api 指导 2.0:here are examples for mysqldb

【讨论】:

  • 谢谢。做到了。出于某种原因,我认为即使在 sql 语句内部,MySQL db 也会弄清楚如何转义参数。但是现在像这样抛出参数是有意义的。
  • 很高兴它帮助了你!我花了很多时间,直到我不久前才意识到这一点:)
  • 这对 SQL 中的通配符和 LIKE 语句有何作用。我在这里问过同样的问题。我想在 cursor.execute() 中发送参数,其中 %s 将用作通配符和 LIKE 语句。
【解决方案3】:

要在 Python 字符串格式化表达式中转义 & 符号,请将 & 符号加倍:

'%%%s%%' % search_string

编辑:但我绝对同意另一个答案。 SQL 查询中的直接字符串替换几乎总是一个坏主意。

【讨论】:

  • 如何使用相同的并将 search_string 作为参数发送到 cursor.execute() 函数。所以这会阻止我进行任何类型的 SQL 注入。
【解决方案4】:

我们可以尝试通过将百分比字符加倍来转义,如下所示:

query_to_get_user_name = """ 
SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag 
ON user.id = tag.userId 
WHERE user.username LIKE '%%%s%%' """ % (user_name,) 

cursor.execute(query_to_get_user_name)

【讨论】:

    【解决方案5】:
    import mysql.connector
    mydatabase = mysql.connector.connect(host="localhost", user="root", passwd="1234", database="databaseName")
    mycursor = mydatabase.cursor()
    user_input =[]
    item = str("s%")
    user_input.append(item)
    mycursor.execute("SELECT * FROM employees WHERE FIRST_NAME LIKE %s ESCAPE ''",user_input )
    result = mycursor.fetchall()
    for row in enumerate(result):
        print(row)
    

    【讨论】:

    • 如果你能描述一下你的代码以及它是如何解决问题的,那就更好了。
    【解决方案6】:

    所以我尝试了这个,我想我得到了一个更容易理解的答案,一个学生。 在我的代码中,表名是“books”,我要搜索的列是“Name”。 如果您需要更多解释,请随时发送邮件至 dhruv2003.joshi@gmail.com,我会尽力尽快回复

    def S():
    
            n=str(input('Enter the name of the book: '))
    
            name='%'+n+'%'
    
            NAME=name
    
            query="select * from books where Name like '"+NAME+"' "
    
            c.execute(query)
    
            ans=c.fetchall()
            
            if len(ans)>0:
                print('')
    
                for i in ans:
    
                    print(i)
    
                 print('')
    
            else:
                print('')
    
                print('An error occured')
    
                print('Name you gave does not exist :( ')
    
                print('')
    

    【讨论】:

      【解决方案7】:

      我有办法解决你的问题:

      你不能使用:

      "SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN tag ON user.id = tag.userId WHERE user.username LIKE '%%s%'" % (query)
      

      你可以用字符串模板来改变它,比如:

      import MySQLdb
      import string # string module
      .......
      value = {'user':'your value'}
      sql_template = string.Template("""
      SELECT tag.userId, count(user.id) as totalRows FROM user INNER JOIN
      tag ON user.id = tag.userId WHERE user.username LIKE '%$user%'
      """)
      
      sql = sql_template.substitute(value)
      
      try:
          cursor.execute(sql)
          ...........
      except:
          ...........
      finally :
         db.close()
      

      【讨论】:

      • 这并不比你不应该做的直接替换更好。如上所述和 PEP 249 文档中描述的占位符描述了如何正确执行此操作
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 2012-06-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多