Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 使用execute_批插入时出现Psycopg2类型错误_Python_Postgresql_Psycopg2 - Fatal编程技术网

Python 使用execute_批插入时出现Psycopg2类型错误

Python 使用execute_批插入时出现Psycopg2类型错误,python,postgresql,psycopg2,Python,Postgresql,Psycopg2,我正在尝试使用psycopg2将批插入到postgres数据库中。我正在使用%s和元组列表,但由于以下错误而失败: File ".../python3.6/site-packages/psycopg2/extras.py", line 1183, in execute_batch sqls = [cur.mogrify(sql, args) for args in page] File ".../python3.6/site-packages/psycopg2/extras.py",

我正在尝试使用psycopg2将批插入到postgres数据库中。我正在使用%s和元组列表,但由于以下错误而失败:

File ".../python3.6/site-packages/psycopg2/extras.py", line 1183, in execute_batch
    sqls = [cur.mogrify(sql, args) for args in page]
  File ".../python3.6/site-packages/psycopg2/extras.py", line 1183, in <listcomp>
    sqls = [cur.mogrify(sql, args) for args in page]
TypeError: not all arguments converted during string formatting
我还尝试用“NULL”字符串替换Nones,但没有效果

VAL是一个元组列表,因此它不是and中常见的问题


我希望这是一个问题的类型,我插入,但在一个不知所措。我已经将psycopg2 python与sql进行了比较,它似乎应该得到验证

显式地将值的数量传递到查询中

import psycopg2
import psycopg2.extras
conn = psycopg2.connect(
    database='mydb',
    user='name',
    password='pass')
    cur = conn.cursor()
query = "INSERT INTO my_table (tweet_id, user_id, time, text, 
    reply_to_user_id, reply_to_tweet_id, reply_to_handle, is_retweet, 
    is_quote, quote_usr_id, quote_usr_handle, quote_id, quote_text, 
    retweet_usr_id, retweet_usr_handle, retweet_id, longitude, latitude, 
    location, time_zone) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);"
#vals are values to insert, a list of tuples
vals = [(123, 123, datetime.datetime(2017, 1, 18, 17, 12, 33), 
    "'Some Text'", None, None, None, None, None, None, None, None, 
    None, 1234, "'username'", 1234, None, None, "'Somewhere'", 
    "'Pacific Time (US & Canada)'"), 
    (321, 321, datetime.datetime(2017, 1, 18, 15, 43, 19), 
    "'More text'", 321, 321, "'person'", None, None, None, None, None,  
    None, None, None, None, None,None, "'faraway'", 
    "'Pacific Time (US & Canada)'")]
psycopg2.extras.execute_batch(cur,query,vals)

显式地将值的数目传递到查询中

import psycopg2
import psycopg2.extras
conn = psycopg2.connect(
    database='mydb',
    user='name',
    password='pass')
    cur = conn.cursor()
query = "INSERT INTO my_table (tweet_id, user_id, time, text, 
    reply_to_user_id, reply_to_tweet_id, reply_to_handle, is_retweet, 
    is_quote, quote_usr_id, quote_usr_handle, quote_id, quote_text, 
    retweet_usr_id, retweet_usr_handle, retweet_id, longitude, latitude, 
    location, time_zone) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s);"
#vals are values to insert, a list of tuples
vals = [(123, 123, datetime.datetime(2017, 1, 18, 17, 12, 33), 
    "'Some Text'", None, None, None, None, None, None, None, None, 
    None, 1234, "'username'", 1234, None, None, "'Somewhere'", 
    "'Pacific Time (US & Canada)'"), 
    (321, 321, datetime.datetime(2017, 1, 18, 15, 43, 19), 
    "'More text'", 321, 321, "'person'", None, None, None, None, None,  
    None, None, None, None, None,None, "'faraway'", 
    "'Pacific Time (US & Canada)'")]
psycopg2.extras.execute_batch(cur,query,vals)

我建议您编写以下类型的函数,而不是编写查询(如果需要,则用于UPSERT):

def execute_upsert(cur, table, champs, rows, champs_unique=None):
    """
        Fonction qui renvoie la requete pour execute_batch(cur, requete, list_rows) de psycopg2
        :param cur: cursor psycopg2
        :param table: Table postgresql, pour l'insertion
        :param champs: List ou Tuple des Champs de la table, pour les insertions
        :param rows: Tableau (list, tuple, generator) des lignes à insérer
        :param champs_unique: Si Upsert, on donne un tuple des champs d'unicité
    """

    def get_sql(t, col, c_u):
        """
            Fonction qui renvoie la requete pour execute_batch(cur, requete, list_rows) de psycopg2
            :param t: Table postgresql, pour l'insertion
            :param col: List ou Tuple des Champs de la table, pour les insertions
            :param c_u: Si Upsert, on donne un tuple des champs d'unicité
            :return: Retourne la Requête
        """
        sql_insert = f'INSERT INTO "{t}" ('
        champs_insertion = []

        for champ in col:
            sql_insert += f'"{champ}", '
            test_champ = "%s"
            champs_insertion.append(test_champ)

        if len(champs_insertion) > 1:
            c = str(tuple(champs_insertion)).replace("'", "")
            sql_insert = sql_insert[:-2] + f') VALUES {c} '
        else:
            c = "(" + str(champs_insertion[0]).replace("'", "") + ")"
            sql_insert = sql_insert[:-2] + f') VALUES {c} '

        if c_u is None:
            sql_insert += 'ON CONFLICT DO NOTHING;'

        else:
            if champs_unique is not None:
                chu = "("
                for value in champs_unique:
                    chu += f'"{value}", '
                chu = f'{chu[:-2]})'
                sql_insert += f' ON CONFLICT {chu} DO UPDATE SET '
                for champ in champs:
                    if champ not in champs_unique:
                        sql_insert += f'"{str(champ)}" = excluded."{str(champ)}", '

                sql_insert = sql_insert[:-2] + ';'

            else:
                sql_insert += ';'

        return sql_insert

    execute_batch(cur, get_sql(table, champs, champs_unique), rows)
这很简单:

execute_upsert(
    cur=cur,
    table=table_projets_colonnesprojet,
    champs=champs_table,
    rows=list_rows,
    champs_unique=("code_comptable",)
)

我建议您编写以下类型的函数,而不是编写查询(如果需要,则用于UPSERT):

def execute_upsert(cur, table, champs, rows, champs_unique=None):
    """
        Fonction qui renvoie la requete pour execute_batch(cur, requete, list_rows) de psycopg2
        :param cur: cursor psycopg2
        :param table: Table postgresql, pour l'insertion
        :param champs: List ou Tuple des Champs de la table, pour les insertions
        :param rows: Tableau (list, tuple, generator) des lignes à insérer
        :param champs_unique: Si Upsert, on donne un tuple des champs d'unicité
    """

    def get_sql(t, col, c_u):
        """
            Fonction qui renvoie la requete pour execute_batch(cur, requete, list_rows) de psycopg2
            :param t: Table postgresql, pour l'insertion
            :param col: List ou Tuple des Champs de la table, pour les insertions
            :param c_u: Si Upsert, on donne un tuple des champs d'unicité
            :return: Retourne la Requête
        """
        sql_insert = f'INSERT INTO "{t}" ('
        champs_insertion = []

        for champ in col:
            sql_insert += f'"{champ}", '
            test_champ = "%s"
            champs_insertion.append(test_champ)

        if len(champs_insertion) > 1:
            c = str(tuple(champs_insertion)).replace("'", "")
            sql_insert = sql_insert[:-2] + f') VALUES {c} '
        else:
            c = "(" + str(champs_insertion[0]).replace("'", "") + ")"
            sql_insert = sql_insert[:-2] + f') VALUES {c} '

        if c_u is None:
            sql_insert += 'ON CONFLICT DO NOTHING;'

        else:
            if champs_unique is not None:
                chu = "("
                for value in champs_unique:
                    chu += f'"{value}", '
                chu = f'{chu[:-2]})'
                sql_insert += f' ON CONFLICT {chu} DO UPDATE SET '
                for champ in champs:
                    if champ not in champs_unique:
                        sql_insert += f'"{str(champ)}" = excluded."{str(champ)}", '

                sql_insert = sql_insert[:-2] + ';'

            else:
                sql_insert += ';'

        return sql_insert

    execute_batch(cur, get_sql(table, champs, champs_unique), rows)
这很简单:

execute_upsert(
    cur=cur,
    table=table_projets_colonnesprojet,
    champs=champs_table,
    rows=list_rows,
    champs_unique=("code_comptable",)
)

值(%s,%s,…。%s)?20个值,我认为您希望在查询中显式传递值的数量。是的,您是对的!我不知道我怎么会错过那个!如果您回答,我会将其标记为正确。很高兴我可以帮助值(%s,%s,.%s)?20个值,我认为您希望在查询中显式传递值的数量。是的,您是对的!我不知道我怎么会错过那个!如果你回答的话,我会把它标记为正确的。很高兴我能帮助你,SQL注入攻击不安全。SQL注入攻击不安全。