You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python执行带IF判断的PostgreSQL写入语句加载数据报错

问题描述

我正尝试使用Python将某地方报社的一系列推文存储到PostgreSQL数据库中。手动通过PgAdmin加载数据时SQL查询运行完全正常,但使用Python自动化执行该流程时出现问题,希望大家可以帮忙排查代码问题。


相关代码

Python逻辑代码

def obtiene_tweets(usuario, auth = auth_titter(), cantidad = 100):
    fuente = obtiene_id(usuario)

    # 连接Twitter API
    api = tweepy.API(auth)

    # 打开数据库连接
    conn = psycopg2.connect(dbname = config.DB_NAME, 
                                user = config.DB_USER,
                                password = config.DB_PASSWORD,
                                host = config.DB_HOST)
    # 遍历拉取推文并存库
    cur = conn.cursor()
    for tweet in tweepy.Cursor(api.user_timeline, screen_name = fuente.loc['usuario',].values[0], tweet_mode= 'extended').items(cantidad):
        full_text = tweet._json['full_text']
        id = fuente.loc['id',].values[0]
        fecha = tweet._json['created_at']
        try: 
            hashtags = str(tweet._json['entities']['hashtags']).replace('[','')
            hashtags = hashtags.replace(']','')
            if hashtags == '':
                hashtags = 'Null'
        except:
            pass
        try:
         url = tweet._json['entities']['urls'][0]['expanded_url']
        except:
            url = 'Null'
        try:
         likes = tweet._json['favorite_count']
         rts = tweet._json['retweet_count']
        except:
            pass
        cur.execute(sql_statements.CARGA_TWEETS, (full_text.replace("'","'"),id,full_text.replace("'","'"), fecha, hashtags, url, likes, rts))
        
    cur.close()
    conn.close()

对应SQL语句

CARGA_TWEETS = """
                DO $$
                BEGIN
                IF EXISTS(SELECT tweet FROM tweets WHERE tweet = %s ) THEN

                raise notice 'Se encuentra el tweet';

                ELSE
                insert into tweets(id_usuario, tweet, fecha, hashtags, urls, likes, rts)
                values(%s, %s, %s, %s, %s, %s, %s );
                

                END IF;

                END $$
            """

报错信息

Traceback (most recent call last):
  File "/media/mariano/Nuevo vol/CarpetaProtegida/Provincia/Propuestas/Proyectos/resumen-noticias/funciomes.py", line 121, in <module>
    obtiene_tweets('clarineconomico')
  File "/media/mariano/Nuevo vol/CarpetaProtegida/Provincia/Propuestas/Proyectos/resumen-noticias/funciomes.py", line 111, in obtiene_tweets
    cur.execute(sql_statements.CARGA_TWEETS, (full_text.replace("'",''),id,full_text.replace("'",''), fecha, hashtags, url, likes, rts))
psycopg2.errors.StringDataRightTruncation: value too long for type character varying(200)
CONTEXT:  SQL statement "insert into tweets(id_usuario, tweet, fecha, hashtags, urls, likes, rts)
                    values(9, 'José Mujica: Me he puesto viejo sintiendo de crisis en Argentina y sin embargo, no sé cómo, pero siempre salen adelante url', 'Fri Aug 27 13:26:22 +0000 2021', 'Null', 'extended_url', 7, 1 )"
PL/pgSQL function inline_code_block line 8 at SQL statement

解决方案

报错的核心原因是你数据库中tweet字段设置的类型是character varying(200),仅支持最多200个字符的存储,而现在要插入的推文内容长度已经超出了这个限制,你可以选择两种方案解决:

  • 调整数据库字段类型:把tweet字段的类型从varchar(200)改成text类型,PostgreSQL的text类型没有固定长度限制,完全可以适配最长的推文内容,修改字段的SQL语句如下:
ALTER TABLE tweets ALTER COLUMN tweet TYPE text;

如果还有其他字段比如urls、hashtags也有超长的可能,也可以同步改成text类型。

  • 入库前截断内容:如果你不需要存储完整的推文内容,也可以在Python代码中对要入库的字符串做截断处理,比如把推文内容限制到199个字符:
full_text = tweet._json['full_text'][:199]

另外现有代码还有两个可以优化的点:

  1. 不需要手动替换单引号,psycopg2的参数化查询会自动处理特殊字符的转义,你写的full_text.replace("'","'")完全没有任何作用,可以直接删掉替换逻辑。
  2. 你现在写的PL/pgSQL的DO块对参数化传递的支持不好,更推荐直接用PostgreSQL原生的INSERT ... ON CONFLICT语法实现存在就跳过的逻辑,性能更好也更稳定,前提是你要给tweet字段加唯一索引。

内容的提问来源于stack exchange,提问作者Mariano Radusky Giobellina

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:51:00