2012-01-12 25 views
13

Sử dụng pysqlite Tôi đang thực hiện một quy trình để thực hiện điều gì đó với một số dữ liệu. Cùng một loại hoạt động được thực hiện trên các lĩnh vực tương tự trong nhiều bảng và cột, vì vậy tôi nghĩ tôi có thể parameterize câu lệnh SQL như hình dưới đây:pysqlite: Thay thế trình giữ chỗ cho tên cột hoặc bảng?

def foo(): 
    column = 'c' 
    table = 't' 
    row = 1 
    # preferred approach, gives syntax error 
    c.execute('SELECT ? FROM ? WHERE id=?', (column, table, row)) 
    # sanity check, works fine 
    c.execute('SELECT c FROM t WHERE id=?', (row)) 
    # workaround, also works, but is this the right way? 
    c.execute('SELECT % FROM % WHERE id=?' % (column, table), row)) 

Các lỗi tôi nhận được không phải là rất hữu ích (sqlite3.OperationalError: near "?": syntax error), nhưng tôi nhận được điểm: Pysqlite không đánh giá cao trình giữ chỗ được sử dụng theo cách này.

Có ai có thể chỉ ra những gì đang diễn ra ở đây cùng với cách thực hiện đúng cách trên?

Trả lời

15

Bạn chỉ đơn giản là không thể sử dụng trình giữ chỗ cho tên cột hoặc bảng. Tôi không có một trích dẫn có thẩm quyền cho điều này - tôi "biết" điều này chỉ từ đã thử nó và từ thất bại. Nó làm cho một số cảm giác mặc dù:

  • Nếu các cột và bảng có thể được parametrized, sẽ có ít mục đích để chuẩn bị (execute -ing) các câu lệnh SQL trước khi lấy, vì tất cả các bộ phận của báo cáo kết quả có thể được thay thế .
  • Tôi không chắc chắn về pysqlite , nhưng MySQLdb tự động trích dẫn tất cả các tham số chuỗi . Tên cột và bảng không được trích dẫn. Vì vậy, nó sẽ làm phức tạp việc phân tích cú pháp theo yêu cầu của người lái xe nếu nó phải quyết định xem trình giữ chỗ có biểu thị cột hoặc tên bảng so với giá trị cần trích dẫn hay không.

Tóm lại, bạn đã tìm đúng cách - sử dụng định dạng chuỗi.

c.execute('SELECT {} FROM {} WHERE id=?'.format(column, table), row)) 

Không phải tất cả tài xế trích dẫn các thông số - oursql không, vì nó sẽ gửi SQL và đối số đến máy chủ riêng biệt.

+0

Tính năng này có an toàn với SQL injection không? – berkelem

+1

@berkelem: Dễ bị tiêm SQL. Thật không may, bởi vì các tên cột và bảng là unparametrizable, không có cách nào để tránh định dạng chuỗi. [Sử dụng danh sách trắng] (https://phpdelusions.net/sql_injection#whitelist) là phương pháp hay nhất ở đây. – unutbu

2

Khi @unutbu trả lời, không có cách nào để sử dụng trình giữ chỗ cho tên bảng/cột. Đề nghị của tôi để làm những gì bạn đang làm bây giờ, nhưng cũng để báo giá tên bảng để bảo vệ mình khỏi một bảng hoặc cột có thể có một tên kỳ lạ.

What does the SQL Standard say about usage of backtick(`)? đã giải thích điều này ở một mức độ nào đó và mặc dù ý kiến ​​trong câu trả lời đó, tôi sẽ nói rằng trong trường hợp của bạn, trích dẫn là một ý tưởng hay.

Các vấn đề liên quan