How to properly escape strings when manually building SQL queries in SQLAlchemy?

前端 未结 4 1018
我在风中等你
我在风中等你 2021-02-14 15:29

I am using SQLAlchemy to connect to different databases in Python, but not with the ORM support as this cannot be implemented due to several reasons.

Mainly I do build a

相关标签:
4条回答
  • 2021-02-14 15:56

    You should not try to implement your own escaping, but should instead use SQLAlchemy's builtin method:

    sql = 'select * from foo where fieldname = :name'
    result = connection.execute(sql, name = myvar)
    
    0 讨论(0)
  • 2021-02-14 15:57

    Compiling and completing other contributors' answers.

    Writing direct SQL strings is often a bad solution, because each database system supports its own SQL dialect, and hence SQL strings are often not portable across databases.

    To abstract this issue away from the users, SQLAlchemy invites you to write your SQL queries at a slightly higher level, in a more object-oriented fashion. It's called the SQL Expression language, and it's documented here: https://docs.sqlalchemy.org/en/13/core/tutorial.html

    Basically, you can build expressions in Python that describe what you want to do, and SQLAlchemy will produce the corresponding SQL string for you, using the appropriate dialect for the database you're using.

    Since you are familiar with SQL, you can learn this "mini-language" in a matter of hour(s) (I'm hesitant to put an "s" here).

    And if I believe @BrtH, using this system will also escape strings for you, transparently. Escaping is hard to get right, and so it's always better to leave it to a mature system than trying to do it yourself.

    Here's a random example of a select clause:

    from sqlalchemy import select
    ...
    ham_table = meta.tables['ham']
    sel = select([ham_table.c.size, ham_table.c.weight]).where(ham_table.c.taste == 'yummy')
    result = meta.bind.execute(sel)
    

    Don't be thrown off by the ".c.", it's just a convention that helps them automate things nicely for you. They basically generate column descriptors for you, and store them under the .c field of your table object.

    0 讨论(0)
  • 2021-02-14 16:10

    In cases where one must explicitly escape a string, and the standard tools don't align with the requirement, you can ask SQLAlchemy to escape using an engine's dialect.

    import sqlalchemy
    
    
    engine = sqlalchemy.create_engine(...)
    sqlalchemy.String('').literal_processor(dialect=engine.dialect)(value="untrusted value")
    

    In my case, I needed to dynamically create a database (sqlalchemy-utils has this functionality but it failed in my case) according to user input.

    0 讨论(0)
  • 2021-02-14 16:16

    You can use escape_string method from pymysql and then escape : so SQLAlchemy won't try to bind parameter for that variable, here is the sample

    import MySQLdb
    query = """ insert into.... values("{}"...) """.format(MySQLdb.escape_string(item).replace(':','\:'))
    

    Note that if you use this way your code vulnerable to SQL Injection to install pymysql

    pip3 install pymysql
    
    0 讨论(0)
提交回复
热议问题