从 CSV NULL 值导入的 PostgreSQL 是文本 - 需要 null
Posted
技术标签:
【中文标题】从 CSV NULL 值导入的 PostgreSQL 是文本 - 需要 null【英文标题】:PostgreSQL import from CSV NULL values are text - Need null 【发布时间】:2021-01-12 22:00:48 【问题描述】:我使用 phpMyAdmin 从 mysql 数据库中将一堆表 (>30) 导出为 CSV 文件。这些 CSV 文件包含 NULL
值,例如:
"id","sourceType","name","website","location"
"1","non-commercial","John Doe",NULL,"California"
我使用 TablePlus 将许多此类 csv 导入到 PostgreSQL 数据库。但是,列中的 NULL
值实际上显示为文本而不是 null。
当我的应用程序从这些列中获取数据时,它实际上检索的是文本 'NULL'
而不是空值。
另外,带有IS NULL
的 SQL 命令也不会检索这些行,可能是因为它们被标识为文本而不是空值。
是否有一个 SQL 命令可以将所有表中的所有文本 NULL
值转换为实际的 NULL 值?这是避免重新导入所有表的最简单方法。
【问题讨论】:
也许写一个简单的脚本来读取 CSV 并插入到表格中? 我的问题更多的是导入完成后要做什么。 问题是为什么NULL在这个字段中而不是一个空(null)字段。除非您需要经常这样做,否则最简单的解决方案是将该列定义为 TEXT 导入到临时表中,然后通过适当的转换选择到最终表中。 @BjarniRagnarsson 你能提供一个例子作为解决方案吗? 一种方法是在选择入决赛表时使用NULLIF函数将NULL字符串转换为null。实际上 - 在这种情况下,您可以直接读入决赛表并运行update table set website=null where website='NULL';
,因为它是一个文本列,NULL 不会导致错误。
【参考方案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'
。
【讨论】:
您能否举例说明一下。如果您可以展示完整示例以帮助可能再次遇到此问题的任何人,我想我会将其标记为答案,因为我上面的答案是非常特定于应用程序的(需要 laravel 和 php)。 用你的数据添加了一个完整的例子。【参考方案2】:更新对于来这里寻找解决方案的人 查看两种潜在解决方案的答案
其中一个解决方案提供了一种 SQL COPY 方法,该方法必须在导入之前执行。该解决方案由 Michal T 提供,并标记为已接受的答案是从一开始就防止这种情况发生的更好方法。 下面的解决方案在我的应用程序中使用了一个脚本(内置于 Laravel/PHP),该脚本可以在导入完成后完成。注意 - 查看代码中的 cmets,您可能会在其他语言/框架中找到类似的解决方案。
感谢上面 cmets 中的@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。
【讨论】:
以上是关于从 CSV NULL 值导入的 PostgreSQL 是文本 - 需要 null的主要内容,如果未能解决你的问题,请参考以下文章