1

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

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

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

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

SQL 命令IS NULL也不会检索这些行,可能是因为它们被标识为文本而不是空值。

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

4

2 回答 2

1

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

您的数据示例:

CSV:

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

桌子:

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'

于 2021-01-13T09:51:39.240 回答
0

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

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

注意 - 查看代码中的注释,您可能会在其他语言/框架中找到类似的解决方案。

感谢上面评论中的@BjarniRagnarsson 建议,我想出了一个简短的 PHP Laravel 脚本来对所有列(类型为“字符串”或“文本”)执行更新查询,以用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。

于 2021-01-13T04:08:32.370 回答