Set empty strings ('') to NULL in the whole database
The most efficient way to achieve this:
- Run a single
UPDATE
per table. - Only update nullable columns (not defined
NOT NULL
) with any actual empty string. - Only update rows with any actual empty string.
- Leave other values unchanged.
This related answer has a plpgsql function that builds and runs the UPDATE
command using system catalog pg_attribute
automatically and safely for any given table:
- Replace empty strings with null values
Using the function f_empty2null()
from this answer, you can loop through selected tables like this:
DO
$do$
DECLARE
_tbl regclass;
BEGIN
FOR _tbl IN
SELECT c.oid::regclass
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relkind = 'r' -- only regular tables
AND n.nspname NOT LIKE 'pg_%' -- exclude system schemas
LOOP
RAISE NOTICE $$PERFORM f_empty2null('%');$$, _tbl;
-- PERFORM f_empty2null(_tbl); -- uncomment to prime the bomb
END LOOP;
END
$do$;
Careful! This updates all empty strings in all columns of all user tables in the DB. Be sure that's what you want or it might nuke your database.
You need UPDATE
privileges on all selected tables, of course.
As a child safety device I commented the payload.
You may have noted that I use the system catalogs directly, not the information schema (which would work, too). About this:
- How to check if a table exists in a given schema
- Query to return output column names and data types of a query, table or view
For repeated use
Here is an integrated solution for repeated use. Without safety devices:
CREATE OR REPLACE FUNCTION f_all_empty2null(OUT _tables int, OUT _rows int) AS
$func$
DECLARE
_typ CONSTANT regtype[] := '{text, bpchar, varchar, \"char\"}';
_sql text;
_row_ct int;
BEGIN
_tables := 0; _rows := 0;
FOR _sql IN
SELECT format('UPDATE %s SET %s WHERE %s'
, t.tbl
, string_agg(format($$%1$s = NULLIF(%1$s, '')$$, t.col), ', ')
, string_agg(t.col || $$ = ''$$, ' OR '))
FROM (
SELECT c.oid::regclass AS tbl, quote_ident(attname) AS col
FROM pg_namespace n
JOIN pg_class c ON c.relnamespace = n.oid
JOIN pg_attribute a ON a.attrelid = c.oid
WHERE n.nspname NOT LIKE 'pg_%' -- exclude system schemas
AND c.relkind = 'r' -- only regular tables
AND a.attnum >= 1 -- exclude tableoid & friends
AND NOT a.attisdropped -- exclude dropped columns
AND NOT a.attnotnull -- exclude columns defined NOT NULL!
AND a.atttypid = ANY(_typ) -- only character types
ORDER BY a.attnum
) t
GROUP BY t.tbl
LOOP
EXECUTE _sql;
GET DIAGNOSTICS _row_ct = ROW_COUNT; -- report nr. of affected rows
_tables := _tables + 1;
_rows := _rows + _row_ct;
END LOOP;
END
$func$ LANGUAGE plpgsql;
Call:
SELECT * FROM pg_temp.f_all_empty2null();
Returns:
_tables | _rows
---------+---------
23 | 123456
Note how I escaped both table and columns names properly!
c.oid::regclass AS tbl, quote_ident(attname) AS col
Consider:
- Table name as a PostgreSQL function parameter
Careful! Same warning as above.
Also consider the basic explanation in the answer I linked above:
- Replace empty strings with null values
Updating empty string to NULL for entire database
I figured out how to do this using a stored procedure. I'd definitely look at using a scripting language next time.
DROP PROCEDURE IF EXISTS settonull;
DELIMITER //
CREATE PROCEDURE settonull()
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE _tablename VARCHAR(255);
DECLARE _columnname VARCHAR(255);
DECLARE cur1 CURSOR FOR SELECT
CONCAT(TABLE_SCHEMA, '.', TABLE_NAME) AS table_name,
COLUMN_NAME AS column_name
FROM information_schema.COLUMNS
WHERE IS_NULLABLE = 'YES'
AND TABLE_SCHEMA IN ('table1', 'table2', 'table3');
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO _tablename, _columnname;
IF done THEN
LEAVE read_loop;
END IF;
SET @s = CONCAT('UPDATE ', _tablename, ' SET ', _columnname, ' = NULL WHERE LENGTH(TRIM(', _columnname, ')) = 0' );
PREPARE stmt FROM @s;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END LOOP;
CLOSE cur1;
END//
DELIMITER ;
CALL settonull();
How do I change all empty strings to NULL in a table?
UPDATE
TableName
SET
column01 = CASE column01 WHEN '' THEN NULL ELSE column01 END,
column02 = CASE column02 WHEN '' THEN NULL ELSE column02 END,
column03 = CASE column03 WHEN '' THEN NULL ELSE column03 END,
...,
column99 = CASE column99 WHEN '' THEN NULL ELSE column99 END
This is still doing it manually, but is slightly less painful than what you have because it doesn't require you to send a query for each and every column. Unless you want to go to the trouble of scripting it, you will have to put up with a certain amount of pain when doing something like this.
Edit: Added the END
s
Change all empty strings to NULL using one query with loop. SQL
@empty
is empty. It doesn't represent the empty string when you concatenate it.
One simple solution is:
SET @empty = '''';
However, you can do the same thing by passing a parameter using sp_executesql
. And I like that approach:
declare @cnt INT = 1959;
while @cnt < 2017
begin
declare @sql nvarchar(1000)
set @sql = 'UPDATE [HDProjEtap1Proba1].[dbo].[TESTGDP] SET [' + CAST(@cnt as nvarchar(255)) + '] = null WHERE ['+ CAST(@cnt as nvarchar(255)) +'] = @empty';
exec sp_executesql @sql, N'@empty nvarchar(255)', @empty = '';
set @cnt = @cnt + 1;
end;
Or event:
declare @cnt INT = 1959;
while @cnt < 2017
begin
declare @sql nvarchar(1000)
set @sql = '
UPDATE [HDProjEtap1Proba1].[dbo].[TESTGDP]
SET [@colname] = null
WHERE [@colname] = @empty';
set @sql = replace(@sql, '@colname', cast(@cnt as varchar(255));
exec sp_executesql @sql, N'@empty nvarchar(255)', @empty = '';
set @cnt = @cnt + 1;
end;
Notice that in this version, the SQL statement is easy to read (and hence to modify and debug). It is defined with parameters that are then subsequently replaced.
Difference between NULL and Blank Value in Mysql
NULL
is an absence of a value. An empty string is a value, but is just empty.NULL
is special to a database.NULL
has no bounds, it can be used forstring
,integer
,date
, etc. fields in a database.NULL
isn't allocated any memory, thestring
withNULL
value is just a pointer which is pointing to nowhere in memory. however, Empty IS allocated to a memory location, although the value stored in the memory is""
.
How to use NULL or empty string in SQL
Select *
From Table
Where (col is null or col = '')
Or
Select *
From Table
Where IsNull(col, '') = ''
How to convert empty spaces into null values, using SQL Server?
Did you try this?
UPDATE table
SET col1 = NULL
WHERE col1 = ''
As the commenters point out, you don't have to do ltrim()
or rtrim()
, and NULL
columns will not match ''
.
Empty string vs NULL
Some differences between them:
NULL
can be assigned to any type, as opposed to empty string which won't be compatible with date/numerical fields.NULL
is an UNKNOWN value, it doesn't have a value as opposed to an empty string, which is a value, but empty one.- As far as I'm aware of,
NULL
shouldn't capture memory as opposed to an empty string which does. null = null
will result innull
as opposed to''=''
which will result inTRUE
.
Related Topics
SQL Server: Any Equivalent of Strpos()
Strategies for Checking Isnull on Varbinary Fields
SQL Syntax to Pivot Multiple Tables
Deleting a Row with a Self-Referencing Foreign Key
SQL Insert into with Subquery and Value
Native Insert Query in Hibernate + Spring Data
Recursive Query for Bill of Materials
Query Featuring Outer Joins Behaves Differently in Oracle 12C
Powershell SQL Select Output to Variable
What Is the Equivalent of Regexp_Substr in MySQL
A Reliable Way to Verify T-SQL Stored Procedures
Oracle Dynamic Desc and Asc in Order By
Reseed Identity Column in SQL Compact
Can You Have a Foreign Key Onto a View of a Linked Server Table in SQLserver 2K5
Passing Lists or Tuples as Arguments in Django Raw SQL
How to Use SQL Wildcards in Linq to Entity Framework
How to Know How Many Rows Will Be Affected Before Running a Query in Microsoft SQL Server 2008