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'
.
我使用 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'
.