簡體   English   中英

使用查詢參數創建 SQL 命令,該參數檢查 NULL 和其他值

[英]Create SQL command with a query parameter that checks for NULL but also for other values

我正在嘗試使用 Python/Postgres 編寫動態 SQL 命令。 在我的 where 子句中,我想使用一個查詢參數(它是用戶定義的),它必須在代碼列 (varchar) 中查找 NULL 值,但在其他情況下也查找特定數字。

如果我必須檢查某個值,我會使用這個:

cursor.execute("""
                    select
                        z.code as code
                    from
                        s_order as o
                    LEFT JOIN
                        s_code as z ON o.id = z.id
                    where
                        z.code = %(own_id)s;
                    """, {
                        'own_id': entry
                    })

但是,如果我必須檢查 NULL 值,則 SQL 和更具體的 WHERE 子句必須是

select
    z.code as code
from
    s_order as o
LEFT JOIN
    s_code as z ON o.id = z.id
WHERE
    z.code IS NULL;

第一個語句中使用的查詢參數不適用於第二個語句,因為它只能替換等式右側的值,而不能替換運算符。 我在這里讀過( https://realpython.com/prevent-python-sql-injection/#using-query-parameters-in-sql )表名也可以使用psycopg2提供的SQL標識符替換,但找不到找出如何替換整個 WHERE 子句或至少是運算符。

不幸的是,我無法更改代碼列中的 NULL 值(例如使用默認值),因為這些 NULL 值是通過 JOIN 操作創建的。

我目前唯一的選擇是根據輸入值使用不同的 SQL 查詢,但是由於 SQL 查詢很長(我為這個問題縮短了它)而且我有很多類似的查詢,它會導致很多類似的代碼...那么我怎樣才能使這個 WHERE 子句動態化?

編輯:除了標記為正確的答案之外,我想添加我自己的解決方案,它不是那么優雅,但在更復雜的場景中可能會有所幫助,因為 NULL 字段被替換為 COALESCE 的“默認”值:

create view orsc as
    select
        coalesce(z.code), 'default') as code
    from
        s_order as o
    LEFT JOIN
        s_code as z ON o.id = z.id;
SELECT
    orsc.code as code2
from
    orsc
WHERE
    code2 = 'default'; //or any other value

EDIT2 :查看標記答案的評論,為什么可能根本不需要視圖。

EDIT3 :這個問題沒有幫助,因為它只要求檢查 NULL 值。 除此之外,答案中顯示的 IF 語句會大大增加我的整個代碼庫(每個查詢都很長,並且經常以稍微調整的方式使用)。

考慮COALESCENULL一個默認值。 下面假設z.code是一個 varchar 或文本。 如果是整數/數字,請將'default'更改為數字值(例如,9999)。

sql = """SELECT
               z.code as code
         FROM
               s_order as o
         LEFT JOIN
               s_code as z ON o.id = z.id
         WHERE
               COALESCE(z.code, 'default') = %(own_id)s;
      """

cursor.execute(sql, {'own_id': entry})    
cursor.execute(sql, {'own_id': 'default'})     # RETURNS NULLs IN z.code

在線演示

我不知道 phyton 語法,但這是一個想法:

condition String;

if own_id = "NULL"{
    condition= " z.code IS NULL ";
}else{
    condition= " z.code = " + own_id;
}

cursor.execute("""
                    select
                        z.code as code
                    from
                        s_order as o
                    LEFT JOIN
                        s_code as z ON o.id = z.id
                    where
                        %(condition);
                    """, {
                        'condition': entry
                    })

正如我在評論中鏈接的解決方案一樣,真的沒有辦法使用if塊。 你可以試試這個:

pre_query="""
                    select
                        z.code as code
                    from
                        s_order as o
                    LEFT JOIN
                        s_code as z ON o.id = z.id
                    where
"""
args={entry}
zcode="z.code = %s"
if entry == None:
   zcode="z.code IS NULL"
   args={}

end_query=";" // other conditions
full_query=pre_query+zcode+end_query

cursor.execute(full_query,args)

如果我理解正確,您希望能夠發送 null 以及其他值並返回正確的結果。 也就是說,問題在於如果 insent 值為空,則比較不會返回任何內容。 這將解決問題 - 可能會稍微降低性能。

cursor.execute("""
                    select
                        z.code as code
                    from
                        s_order as o
                    LEFT JOIN
                        s_code as z ON o.id = z.id
                    where
                        z.code is not distinct from %(own_id)s;
                    """, {
                        'own_id': entry
                    })

此致,
比亞尼

您可以使用z.code IS NOT DISTINCT FROM %(own_id)s這就像=但其中 NULL 被視為正常值(即 NULL = NULL, NULL != 任何非空值)。

請參閱Postgres 比較運算符

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM