Python使用to_sql写入Redshift报value too long for character varying(256)错误
问题根因
报错psycopg2.errors.StringDataRightTruncation: value too long for type character varying(256)的核心原因是:
- pandas调用
to_sql方法自动建表时,默认会把DataFrame里的字符串类型字段映射为Redshift的VARCHAR(256)类型 - 你的
text字段存在长度超过256个字符的内容,写入时触发长度超出限制的报错 - 可以正常导出本地CSV是因为本地文件没有字段长度校验规则,不会触发该错误
解决方案
你可以通过指定to_sql的dtype参数,自定义每个字段在Redshift中的数据类型,规避默认长度限制:
- 对于长度不固定的长文本字段,直接指定为
TEXT类型,Redshift的TEXT类型没有长度上限,适合存储混合长度的字符串 - 如果需要固定长度限制,可以先计算字段的最大长度,指定为对应长度的
VARCHAR类型
小提示:如果数据量超过万行,不推荐使用
to_sql写入Redshift,该方式是逐行插入性能极低,推荐先将DataFrame导出为CSV上传到S3,再调用Redshift的COPY命令加载数据,效率会提升10倍以上。
优化后的代码示例
import io import boto3 import pandas as pd from sqlalchemy import create_engine from sqlalchemy.types import TIMESTAMP, Integer, TEXT # 导入需要的字段类型 from datetime import datetime client = boto3.client('s3', aws_access_key_id="", aws_secret_access_key="") response = client.get_object(Bucket='', Key='*.csv') file = response['Body'].read() df = pd.read_csv(io.BytesIO(file)) df['date'] = pd.to_datetime(df['date'], infer_datetime_format=True) df['text'] = df['text'].astype(str) df['count'] = df['count'].fillna(0).astype(int) con = create_engine('postgresql://*.redshift.amazonaws.com:5439/dev') select_list = ['date','text','count'] write_df = df[select_list] # 新增字段类型映射配置 dtype_map = { 'date': TIMESTAMP(), 'text': TEXT(), 'count': Integer() } # 写入时传入dtype参数 write_df.to_sql('test', con, schema='parent', index=False, if_exists='replace', dtype=dtype_map)
内容的提问来源于stack exchange,提问作者Dinesh
相关产品推荐
相关产品推荐

