【问题标题】:django - raw SQL queries compatibilitydjango - 原始 SQL 查询兼容性
【发布时间】:2026-02-05 06:30:01
【问题描述】:

我有一个超过 80 行的原始 SQL 查询,我无法使用查询集重现这些结果。我现在想让这个查询与 SQLite 和 PostgreSQL 兼容,这样它就可以在开发和生产环境中运行。

是否有任何推荐或内置的方法来继续?

示例

因此,例如,我得到了这个 PostgreSQL 语法错误:

operator does not exist: boolean = integer

我调整了语法并使用了一些条件来为每种情况获取正确的 SQL 字符串,但这对我来说是错误的:

db_engine = ''
engine = settings.DATABASES['default']['ENGINE']
if re.match('.*sqlite3$', engine):
    db_engine = 'sqlite3'
elif re.match('.*psycopg2$', engine):
    db_engine = 'postgresql'
elif re.match('.*mysql$', engine):
    db_engine = 'mysql'

cursor = connection.cursor()
cursor.execute("""
    ... some big query here ...
    WHERE 1=1
        AND some_boolean_field = %(value)s
""" % {
    'value': 'TRUE' if db_engine == 'postgresql' else '1'
})

【问题讨论】:

  • 我会这样做 - 使用 sring 格式仅更改查询的选定部分,具体取决于 settings.DEBUG 是真还是假

标签: sql django sqlite postgresql


【解决方案1】:

SQLite doesn't have boolean。因此,如果您希望查询在两个数据库中都能正常工作,我建议您在编写原始 SQL 时避免使用 boolean 类型。

boolean 无论如何实际上并没有为您带来任何好处,除非您将大量布尔字段打包在一起,因为它们每个都已经是一个字节,并且出于对齐原因往往会被填充到一个单词中。

观察原始类型大小:

regress=> SELECT pg_column_size(TRUE), pg_column_size(SMALLINT '1');
 pg_column_size | pg_column_size 
----------------+----------------
              1 |              2
(1 row)

考虑到行标题后,差异会更小:

regress=> SELECT 
             pg_column_size( ROW(SMALLINT '1', SMALLINT '1', SMALLINT '0', SMALLINT '1') ),
             pg_column_size( ROW(true, true, false, true) );
 pg_column_size | pg_column_size 
----------------+----------------
             32 |             28
(1 row)

这是四个连续布尔字段的最佳值。实际上,对齐限制往往意味着您最好还是在大多数情况下只使用 smallint。

如果您确实想使用 boolean 来很好地使用 SQLite,则需要将所有内容都转换为整数。这在 SQLite 上将是一个无操作(因此它会在那里工作),并且在 PostgreSQL 上会将布尔值转换为 int。

 AND CAST(some_boolean_field AS integer) = CAST (%(value)s AS integer)

这也可以让您摆脱 PostgreSQL 布尔值的特殊情况;只需传递 1 表示 true / 0 表示 false 并使用:

 AND CAST(some_boolean_field AS integer) = %(value)s

.... 或者,当然,您可以在开发和生产中使用相同的引擎对 PostgreSQL 进行测试。这样,当您实时推送更改时,您就不会遇到令人讨厌的惊喜。我写了一些关于调整 PostgreSQL 安装以用于一次性测试的方法in this earlier post

【讨论】:

  • 太棒了。谢谢。如果我的表中有大量行,那么布尔性能问题会怎样。那会有什么不同吗?
  • @ViniciusMassuchetto 您设想的性能问题是什么?除非行非常宽(即许多相邻的布尔列),否则您不会看到太大的差异。如果您要存储非常宽的行,其中包含大量布尔值,无论如何这可能是“设计气味”。查看varbit 或类似的(如果您决定使用 SQLite,请放弃使用它进行测试)。
  • 现在我明白了,@CraigRinger。谢谢。