【问题标题】:DatabaseError at /post/113/ value too long for type character varying(10)/post/113/ 处的 DatabaseError 值对于类型字符变化而言太长(10)
【发布时间】:2012-11-24 00:51:49
【问题描述】:

我在 Heroku 上为我的 Django 应用程序使用 postgresql。当我尝试为我的帖子发表评论时,我有时会收到此错误(同样,有时并非总是如此)。

尽管出现错误,注释仍然保存,但是save()后面的所有代码都没有执行。

这个问题只发生在 postgresql 上。在我使用 sqlite 的本地主机上,一切正常。

我不确定这是什么原因。

这就是我的模型的样子

class Comment(models.Model):
    post = models.ForeignKey(post)
    date = models.DateTimeField(auto_now_add=True)
    comment = models.TextField()
    comment_user = models.ForeignKey(User)

这就是我的评论模型的样子。 那么是不是因为我没有添加 max_length 进行评论? 这是回溯

DatabaseError at /post/114/
value too long for type character varying(10)
Request Method: POST
Request URL:    http://www.mysite.com/post/114/
Django Version: 1.4.1
Exception Type: DatabaseError
Exception Value:    
value too long for type character varying(10)
Exception Location: /app/.heroku/venv/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py in execute, line 52
Python Executable:  /app/.heroku/venv/bin/python2.7
Python Version: 2.7.2
Python Path:    
['/app',
 '/app/.heroku/venv/bin',
 '/app/.heroku/venv/lib/python2.7/site-packages/pip-1.1-py2.7.egg',
 '/app/.heroku/venv/lib/python2.7/site-packages/distribute-0.6.31-py2.7.egg',
 '/app',
 '/app/.heroku/venv/lib/python27.zip',
 '/app/.heroku/venv/lib/python2.7',
 '/app/.heroku/venv/lib/python2.7/plat-linux2',
 '/app/.heroku/venv/lib/python2.7/lib-tk',
 '/app/.heroku/venv/lib/python2.7/lib-old',
 '/app/.heroku/venv/lib/python2.7/lib-dynload',
 '/usr/local/lib/python2.7',
 '/usr/local/lib/python2.7/plat-linux2',
 '/usr/local/lib/python2.7/lib-tk',
 '/app/.heroku/venv/lib/python2.7/site-packages',
 '/app/.heroku/venv/lib/python2.7/site-packages/PIL']
Server time:    Wed, 5 Dec 2012 20:41:39 -0600

【问题讨论】:

标签: django postgresql heroku


【解决方案1】:

我无法帮助您处理 Django 部分(抱歉),所以我只会说 PostgreSQL。

在您的应用程序中某处您有一个varchar(10) 列,并且您试图在其中放入超过 10 个字符的内容,您可能在某处缺少验证。 SQLite 忽略varchar(n) 列中的大小,并将其视为没有大小限制的text;所以你可以用 SQLite 做这样的事情:

sqlite> create table t (s varchar(5));
sqlite> insert into t (s) values ('Where is pancakes house?');
sqlite> select * from t;
s
where is pancakes house?

毫无怨言。同样,SQLite 可以让你做一些荒谬的事情,比如将字符串放入数字列。

这是你需要做的:

  1. 在 PostgreSQL 上进行部署时,停止在 SQLite 上进行开发。在本地安装 PostgreSQL 并在此基础上进行开发,您甚至应该安装将在 Heroku 使用的相同版本的 PostgreSQL。数据库之间有各种各样的差异会让你头疼,这个小字段大小问题只是你对跨数据库问题的温和介绍。
  2. 停止在 PostgreSQL 中使用 varchar(n),只需使用 text。在 PostgreSQL 中使用大小有限的字符串列是没有意义的,除非您有一个必须限制大小的硬性要求。来自fine manual

    短字符串(最多 126 字节)的存储要求是 1 字节加上实际字符串,其中包括字符情况下的空格填充。较长的字符串有 4 个字节的开销,而不是 1 个。长字符串由系统自动压缩,因此对磁盘的物理要求可能会更少。 [...] 如果您希望存储没有特定上限的长字符串,请使用 text...

    提示:这三种类型之间没有性能差异,除了使用空白填充类型时增加了存储空间,以及存储到长度时需要额外的几个CPU周期来检查长度- 约束列。虽然character(n) 在其他一些数据库系统中具有性能优势,但在 PostgreSQL 中没有这样的优势;事实上,character(n) 通常是三者中最慢的,因为它有额外的存储成本。在大多数情况下,应该使用 textcharacter varying

    所以不要在 PostgreSQL 中使用传统的 charvarchar,除非你必须使用 text

  3. 开始验证您的传入数据,确保它不违反您的任何大小或格式限制。

您可以立即将列从varchar(n) 切换到text,并在启动和运行 PostgreSQL 的同时继续使用 SQLite;对于无限长度的字符串,两个数据库都会对text 感到满意,这个简单的修复将帮助您解决眼前的问题。然后,尽快将开发环境切换到 PostgreSQL,以便在代码投入生产之前发现此类问题。

【讨论】:

  • 当我在 cmets 中只添加一个“hi”时甚至会发生这种情况。它有时会发生。其他时候即使写了一个段落也不会出现错误
  • @Jonathan:那么您需要获取有关该错误的更多信息。你在任何地方都有varchar(10)吗?您是否可能使用字符串来保存应该采用 ISO 8601 格式 (yyyy-mm-dd) 的日期?
  • 我也在问题中添加了我的模型,请看一下。不,我不认为我没有使用字符串来保存日期。
  • 能否包含对应表的 SQL 架构?在 SQLite 中使用 .schema table_name 或在 psql 中使用 \d table_name
  • 我终于找到了问题所在。它实际上是另一个具有 max_length=10 的 CharField 的模型。我也试图在我的代码中操纵该字段。所以这引起了所有的混乱。
【解决方案2】:

原因是 PostgreSQL 实际上会根据字段的大小检查数据的长度,如果太大就会出错,而 SQLite 完全忽略指定的字段大小,MySQL 会默默地截断数据,无法挽回地破坏它。使字段更大。

【讨论】:

  • 我也添加了我的模型。能否请您看一下,让我知道是不是因为我没有添加 max_length 进行评论?
  • 我终于找到了问题所在。它实际上是另一个具有 max_length=10 的 CharField 的模型。我也试图在我的代码中操纵该字段。所以这引起了所有的混乱。
猜你喜欢
  • 2012-02-20
  • 2021-03-02
  • 2016-05-25
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
  • 2021-12-20
  • 1970-01-01
  • 2021-10-20
相关资源
最近更新 更多