如何使N前缀与SQL Server Upsert语句配合使用?

qfe3c7zg  于 2023-01-12  发布在  SQL Server
关注(0)|答案(1)|浏览(107)

我使用绑定参数从pyodbc发送了以下SQL。

IF NOT EXISTS (
        SELECT *
        FROM dbo.tApplicationCMSNegativeFactors2
        WHERE N'transientkey' = N'67'
        )
    INSERT dbo.tApplicationCMSNegativeFactors2 (
    N'transientkey, nfid, active, applicationnum, modstamp, source_database_tablename_for_kafka_connector, source_identifier_for_kafka_connector'
    )
    VALUES (
    N'''67'', ''5'', ''1'', ''52'', ''2022-10-01 03:28:25.000372'', ''tapplicationcmsnegativefactors'', ''transientkey'''
    )
ELSE
    UPDATE dbo.tApplicationCMSNegativeFactors2
    SET N'transientkey = ''67'', nfid = ''5'', active = ''1'', applicationnum = ''52'', modstamp = ''2022-10-01 03:28:25.000372'', source_database_tablename_for_kafka_connector = ''tapplicationcmsnegativefactors'', source_identifier_for_kafka_connector = ''transientkey'''
    WHERE N'transientkey' = N'67';

我不知道为什么,但当尝试执行这段代码时,SSMS中的set子句旁边显示了一个错误。我该怎么做才能使这个sql成功执行,但仍然保留N前缀,以便我可以使它与pyodbc一起工作?
我希望这段代码能够成功执行,因为删除N前缀可以使代码执行。
包括下面的python代码。

import pyodbc

# Auth.
server = ""
database = ""
username = ""
password = ""

# Set up the database connection
cnxn = pyodbc.connect(f'DRIVER={"SQL Server"};SERVER={server};DATABASE={database};UID={username};PWD={password}')
cursor = cnxn.cursor()

ls = [
    "transientkey",
    67,
    "transientkey, nfid, active, applicationnum, modstamp, source_database_tablename_for_kafka_connector, source_identifier_for_kafka_connector",
    "'67', '5', '1', '52', '2022-10-01 03:28:25.000372', 'tapplicationcmsnegativefactors', 'transientkey'",
    "transientkey = '67', nfid = '5', active = '1', applicationnum = '52', modstamp = '2022-10-01 03:28:25.000372', source_database_tablename_for_kafka_connector = 'tapplicationcmsnegativefactors', source_identifier_for_kafka_connector = 'transientkey'",
]

# Execute SQL
def exec_sql(kv, join_kv, col_inst, val_inst, val_upd):
    cursor.execute(
        "IF NOT EXISTS (SELECT * FROM dbo.tApplicationCMSNegativeFactors2 WHERE ? = ?) INSERT tApplicationCMSNegativeFactors2 (?) VALUES (?) ELSE UPDATE dbo.tApplicationCMSNegativeFactors2 SET ? WHERE ? = ?", kv, join_kv, col_inst, val_inst, val_upd, kv, join_kv
    )

exec_sql(str(ls[0]), str(ls[1]), str(ls[2]), str(ls[3]), str(ls[4]))
ruoxqz4g

ruoxqz4g1#

你混淆了参数和动态SQL,你不能用参数改变SQL的结构,所以
tApplicationCMSNegativeFactors2 (?) VALUES (?)
在将带有参数标记?的字符串发送到游标之前,需要使用字符串插值(考虑SQL注入漏洞)完成。
我在这里使用?的原因是为了防止来自python代码的SQL注入攻击。
如果你想避免使用动态SQL,你可以使用一些带有数据参数标记的静态SQL查询,比如

... INSERT tApplicationCMSNegativeFactors2 (transientkey, nfid, active, applicationnum, modstamp, source_database_tablename_for_kafka_connector, source_identifier_for_kafka_connector) VALUES (?,?,?,?,?) ...

相关问题