# Vbulletin 批量导入程序：关系 "topics" 的列 "pinned\_globally" 中的空值违反了非空约束

**URL:** <https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162>\
**Category:** Development\
**Created:** [2025年五月14日 20:48 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162 "2025-05-14T20:48:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)\
**Post date:** [2025年五月14日 20:48 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162/1 "2025-05-14T20:48:09Z")

</div>

我正在尝试使用 vbulletin 批量导入器进行导入。我设法让它大部分完成了。它创建了用户和帖子，但主题没有被创建。

传递给 `create_topics(topics)` 的内容看起来是正确的。`base.rb:create_records` 中 `processed` 中的内容看起来是正确的（skipped 未设置）。但没有主题被创建。

这是错误：

```plaintext
ERROR: column "pinned_globally" of relation "topics" contains null value violates not-null constraint

```

但是，如果一个主题没有被全局置顶，它应该有什么值？我正在尝试在 `base.rb` 中注释掉 `TOPIC_COLUMNS` 中的该字段。

编辑：我认为这可能会解决问题，但需要一段时间才能知道：

```plaintext
    create_topics(topics) do |row|
      created_at = Time.zone.at(row[5])

      t = {
        imported_id: row[0],
        title: normalize_text(row[1]),
        category_id: category_id_from_imported_id(row[2]),
        user_id: user_id_from_imported_id(row[3]),
        closed: row[4] == 0,
        created_at: created_at,
        views: row[6] || 0,
        visible: row[7] == 1,
        pinned_globally: row[8] == 1 # <============== JP added this:
      }
      t[:pinned_at] = created_at if row[8] == 1

      t
    end

```

---

<div class="post-metadata">

**Author:** ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)\
**Post date:** [2025年五月14日 21:47 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162/2 "2025-05-14T21:47:31Z")

</div>

这很奇怪，因为该列有一个默认值？在您执行 `\\d topics` 时，您的数据库中是否有默认值？

` pinned_globally | boolean | | not null | false`

---

<div class="post-metadata">

**Author:** ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)\
**Post date:** [2025年五月14日 21:51 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162/3 "2025-05-14T21:51:41Z")

</div>

嗯。我想这解释了为什么它不在代码中。

但这并没有解开谜团。

```plaintext
pinned_globally | boolean | | not null | false

```

编辑：

随机 AI 说：

> [@](#):
>
> - \*\*批量插入或数据摄取：\*\*如果您使用始终指定所有列（即使带有默认值）的批量插入工具或框架，PostgreSQL 将不会使用列的默认值，而是使用工具提供的[7](https://github.com/borisdj/EFCore.BulkExtensions/issues/769)[10](https://stackoverflow.com/questions/48078788/performance-impact-of-default-value-set-on-tables-column-in-postgresql)提供的值。

也许这是一个“批量插入工具”？

> [@](#):
>
> 当使用 PostgreSQL 中的 `COPY` 命令时，Ruby 中的 `put_copy_data` 会与之交互，该命令不会自动应用表中为未在复制数据中明确提供的列定义的默认值。这意味着，如果您使用 `put_copy_data` 导入数据，并且没有为具有默认值的列提供值，则不会应用默认值。相反，该列将设置为 `NULL`，除非您在复制数据中明确为其提供值。

我找不到任何可靠的来源说明上述引述的内容，但它确实有道理，因为这里的重点是速度快，所以跳过默认值似乎是它会做的事情，而且它确实解释了正在发生的事情，并且，我希望，我仍在等待看是否有效的解决方案。

这是实际文档！[PostgreSQL: Documentation: 18: COPY](https://www.postgresql.org/docs/current/sql-copy.html)

如果指定了列列表，`COPY TO` 只会将指定列中的数据复制到文件中。对于 `COPY FROM`，文件中的每个字段将按顺序插入到指定的列中。`COPY FROM` 列列表中未指定的表列将接收其默认值。

所以，如果我没看错的话，如果一个字段在字段列表中，那么 postgres 会盲目地复制你给它的东西，并且会插入空/null 而不是期望的默认值。

速度越来越慢。有没有理由不像常规导入器那样使用 `LIMIT 1000`？一次处理 885K 个主题似乎有点多？

---

<div class="post-metadata">

**Author:** ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)\
**Post date:** [2025年五月15日 05:17 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162/4 "2025-05-15T05:17:33Z")

</div>

{“translation”: "我检查了我最后一次批量导入的脚本，确实有明确的 `pinned_globally: false`，所以这显然是必要的 — 这是代码中唯一显式硬编码的列值。

```ruby
    create_topics(topics) do |row|
      t = {
        imported_id: row[0],
        title: my_normalize_text(row[1]),
        category_id: category_id_from_imported_id(row[2]),
        user_id: user_id_from_imported_id(row[3]),
        created_at: Time.zone.at(row[4]),
        pinned_globally: false
      }

```

奇怪的是，它没有像 `closed` 或 `has_summary` 等其他类似的 `not null, default false` 列那样设置这个参数。

[引用者=“pfaffman, 第3帖, 主题=366162”]  
导入速度越来越慢。是否有理由不用 LIMIT 1000，就像常规导入器那样？似乎一次处理大约 88 万个主题可能太多了？  
[/引用]  
我上一次使用批量导入器导入的速度是大约 2 小时内完成了 300 万多个主题。可能是你的内存泄漏？或者可能是你用来读取源数据的 MySQL 代码（或者你用的其他任何工具）某个地方很慢？"}

---

<div class="post-metadata">

**Author:** ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)\
**Post date:** [2025年五月15日 13:44 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162/5 "2025-05-15T13:44:11Z")

</div>

好消息！所有主题都已创建！坏消息！没有帖子与它们相关联，但希望这是因为帖子是在主题创建之前创建的。

> [@RGJ](#):
>
> 奇怪的是，它没有为其他类似的 `not null, default false` 列（如 `closed` 或 `has_summary`）提供此功能。

这很奇怪。我确信我有一个解释。 🤷

> [@RGJ](#):
>
> 我上次使用批量导入器进行的导入在 2 小时左右完成了 300 万多个主题。也许你遇到了内存泄漏？或者也许你的 MySQL 代码（或你用来读取源数据的任何东西）在某个地方很慢？

700 万个帖子只花了几个小时，但不到 100 万个主题却花了大约 4 个小时。

这是一台旧机器（他们显然是专门为此工作而购买的？），并且 `mysql` 是远程的。查看 `htop`，系统级别没有明显的内存泄漏。我已经删除了所有数据，并正在重建容器，看看这次是否能正常工作。

非常感谢你的帮助。

---

<div class="post-metadata">

**Author:** ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)\
**Post date:** [2025年五月15日 16:41 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162/6 "2025-05-15T16:41:32Z")

</div>

好吧，现在 user\_email 导入失败，错误信息如下：

```plaintext
CONTEXT: COPY user_emails, 第1行："1 \N @gmail.com true 2004-03-08 14:12:00 UTC 2004-03-08 14:12:00 UTC"

```

---

<div class="post-metadata">

**Author:** ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)\
**Post date:** [2025年五月15日 18:59 UTC](https://meta.discourse.org/t/vbulletin-bulk-importer-null-value-in-column-pinned-globally-of-relation-topics-violates-not-null-constraint/366162/7 "2025-05-15T18:59:23Z")

</div>

> [@RGJ](#):
>
> 奇怪的是，对于其他类似的 `not null, default false` 列，如 `closed` 或 `has_summary`，它却没有这样做。

又花了几个小时，我终于明白了原因——`process_topic` 函数处理了所有这些默认值。

> <https://github.com/discourse/discourse/blob/main/script/bulk_import/base.rb#L1480-L1496>

我猜应该有一个

```plaintext
topic[:pinned_globally] ||= false

```

或者也许

```plaintext
topic[:pinned_globally] ||= topic[:pinned_at].nil?

```
