PostgreSQL 从 CSV 导入 NULL 值是文本 - 需要 null

PostgreSQL import from CSV NULL values are text - Need null

我使用 phpMyAdmin 从 MySQL 数据库中导出了一堆表格 (>30) 作为 CSV 文件。这些 CSV 文件包含 NULL 个值,例如:

"id","sourceType","name","website","location"
"1","non-commercial","John Doe",NULL,"California"

我使用 TablePlus 将许多这样的 csv 导入到 PostgreSQL 数据库中。但是,列中的 NULL 值实际上显示为文本而不是空值。

当我的应用程序从这些列中提取数据时,它实际上检索的是文本 'NULL' 而不是空值。

此外,带有 IS NULL 的 SQL 命令不会检索这些行,可能是因为它们被识别为文本而不是空值。

是否可以使用 SQL 命令将所有表中的所有文本 NULL 值转换为实际的 NULL 值?这将是避免重新导入所有表的最简单方法。

更新对于来这里寻找解决方案的人 查看两个潜在解决方案的答案

  • 其中一个解决方案提供了 SQL COPY 方法,该方法必须在导入本身之前执行。该解决方案由 Michal T 提供并标记为已接受的答案是首先防止这种情况发生的更好方法。
  • 我下面的解决方案在我的应用程序中使用了一个脚本(内置于 Laravel/PHP),它可以在导入完成后完成。

注意- 请参阅代码中的注释,您可能会在其他 languages/frameworks.

中找到类似的解决方案

感谢@BjarniRagnarsson 在上面评论中的建议,我想出了一个简短的 PHP Laravel 脚本来对所有列(类型为 'string' 或'text') 将 'NULL' 文本替换为 NULL 值。

    public function convertNULLStringToNULL()
    {
        $tables = DB::connection()->getDoctrineSchemaManager()->listTableNames(); //Get list of all tables
        $results = []; // an array to store the output results
        foreach ($tables as $table) { // Loop through each table
            $columnNames =  DB::getSchemaBuilder()->getColumnListing($table); //Get list of all columns

            $columnResults = []; // array to store the results per column
            foreach ($columnNames as $column) { Loop through each column
                $columnType = DB::getSchemaBuilder()->getColumnType($table, $column); // Get the column type
                if (
                    $columnType == 'string' || //check if column type is string or text
                    $columnType == 'text'
                ) {
                    $query = "update " . $table . " set \"" . $column . "\"=NULL where \"" . $column . "\"='NULL'"; //Build the update query as mentioned in comments above

                    $r = DB::update($query); //perform the update query
                    array_push($columnResults, [
                        $column => $r
                    ]); //Push the column Results
                }
            }

            array_push($results, [
                $table => $columnResults
            ]); // push the table results
        }

        dd($results); //Output the results
    }

请注意,我为此使用了 Laravel 8。

PostgreSQL 的 COPY 命令具有 NULL 'some_string' 选项,允许将任何字符串指定为 NULL 值:https://www.postgresql.org/docs/current/sql-copy.html 这当然需要重新导入所有 tables.

您的数据示例:

CSV:

"id","sourceType","name","website","location"
"1","non-commercial","John Doe",NULL,"California"
"2","non-commercial","John Doe",NULL,"California"

table:

CREATE TABLE import_with_null (id integer, source_type varchar(50), name varchar(50), website varchar(50), location varchar(50));

COPY语句:

COPY import_with_null (id, source_type, name, website, location) from '/tmp/import_with_NULL.csv' WITH (FORMAT CSV, NULL 'NULL', HEADER);

测试将 NULL 字符串正确导入为 SQL NULL:

SELECT * FROM import_with_null WHERE website IS NULL;
 id |  source_type   |   name   | website |  location  
----+----------------+----------+---------+------------
  1 | non-commercial | John Doe |         | California
  2 | non-commercial | John Doe |         | California
(2 rows)

将 NULL 字符串转换为 SQL NULL 值的重要部分是 NULL 'NULL' 并且可以是任何其他值 NULL 'whatever string'.