SQL if statement to fix issue - postgresql

I have this select
insert into test(t_name)
(select users.first_name || '_' || users.last_name
|| '_' || to_date($values.report_date, 'YYYY.MM.DD')
from users where users.id = $session.user_id)
which works as supposed, except I want it if users.first_name/users.last_name are null and user_id=0 to insert another string 'admin' otherwise I get error because it violates not-null constraint on column t_name.
Any suggestions are appreciated. Thanks.

Use a CASE in the SELECT part:
insert into test (t_name)
select case
when users.first_name is null and users.last_name is null and users.id=0 then 'admin'
else users.first_name || '_' || users.last_name || '_' || to_date($values.report_date,'YYYY.MM.DD')
end
from users
where users.id = $session.user_id
It's not clear (to me) from the question if all conditions you mentioned have to be true or just one of them. Depending on what you want, you should change the ANDs to ORs in the first WHEN part.
(Note that there is no need to enclose the SELECT in () for an INSERT ... SELECT statement)

If you are using MySQL you can use IFNULL.
INSERT INTO test(t_name)
(
SELECT IFNULL(users.first_name || '_' || users.last_name || '_' || to_date($values.report_date, 'YYYY.MM.DD'), 'admin')
FROM users
WHERE users.id = $session.user_id
)
In MSSQL there is a similar ISNULL function, I assume that there is likewise solutions for other database systems.

Related

Postgres generate sql output using data dictionary tables

All I need is to get a SQL query output as :
ALTER TABLE TABLE_NAME
ADD CONSTRAINT
FOREIGN KEY (COLUMN_NAME)
REFERENCES (PARENT_TABLE_NAME);
I'm running the below DYNAMIC query USING DATA DICTIONARY TABLES,
SELECT DISTINCT
'ALTER TABLE ' || cs.TABLE_NAME ||
'ADD CONSTRAINT' || rc.CONSTRAINT_NAME ||
'FOREIGN KEY' || c.COLUMN_NAME ||
'REFERENCES' || cs.TABLE_NAME ||
' (' || cs.CONSTRAINT_NAME || ') ' ||
' ON UPDATE ' || rc.UPDATE_RULE ||
' ON DELETE ' || rc.DELETE_RULE
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC,
INFORMATION_SCHEMA.TABLE_CONSTRAINTS CS,
INFORMATION_SCHEMA.COLUMNS C
WHERE cs.CONSTRAINT_NAME = rc.CONSTRAINT_NAME
AND cs.TABLE_NAME = c.TABLE_NAME
AND UPPER(cs.TABLE_SCHEMA) = 'SSP2_PCAT';
But here even though I'm able to generate the desired output, the concern is its not giving the PARENT_TABLE_NAME here,
rather its giving the same table_name after the ALTER TABLE Keywords.
I hope this is clear as we are using Dynamic SQL here and any help is absolutely appreciated!
Your query is missing a couple of join tables and join conditions. Also, don't forget that a foreign key can be defined on more than one column. Finally, your query is vulnerable to SQL injection via object names.
But it would be much simpler if you used pg_catalog.pg_constraint rather than the `information_schema':
SELECT format('ALTER TABLE %s ADD CONSTRAINT %I %s',
conrelid::regclass,
conname,
pg_get_constraintdef(oid))
FROM pg_catalog.pg_constraint
WHERE contype = 'f'
AND upper(connamespace::regnamespace::text) = 'SSP2_PCAT';

PostgreSQL concatenate integer and real and add units

I want to concatenate 4 columns in a PostgreSQL query and add units if columns aren't empty.
SELECT
CASE
WHEN a.length_m notnull THEN a.length_m || 'm'
WHEN a.area_ar notnull THEN a.area_ar || 'ar'
WHEN a.vol notnull THEN a.vol || 'cbm'
WHEN a.pcs notnull THEN a.pcs || 'pcs'
END as quant;
FROM actions a;
This works fine, but if I have values in two colums it only shows me the first one.
How must I change my query, so that a second WHEN gets evaluated?
Use COALESCE:
SELECT COALESCE(a.length_m ||'m', '') ||
COALESCE(a.area_ar ||'ar', '') ||
COALESCE(a.vol ||'cbm', '') ||
COALESCE(a.pcs ||'pcs', '') as quant
FROM actions a;

How do I find all the NUMERIC columns in a table and do a SUM() on them?

I have a few tables in Netezza, DB2 and PostgreSQL databases, for which I need to reconcile and the best way we have come out with is to do a SUM() across all the NUMERIC Table columns on all the 3 databases.
Does anyone have a quick and simple way to find all the COLUMNS which are either NUMERIC or INTEGER or BIGINT and then run a SUM() on all these?
For comparing the results, I can do it manually also, or if someone has a way to capture these results in a common table and automatically check the differences in the SUM?
For DB2 you can use this metadata which will help you to find out the data type for each column
SELECT
COLUMN_NAME || ' ' || REPLACE(REPLACE(DATA_TYPE,'DECIMAL','NUMERIC'),'CHARACTER','VARCHAR') ||
CASE
WHEN DATA_TYPE = 'TIMESTAMP' THEN ''
ELSE
' (' ||
CASE
WHEN CHARACTER_MAXIMUM_LENGTH IS NOT NULL THEN CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(30))
WHEN NUMERIC_PRECISION IS NOT NULL THEN CAST(NUMERIC_PRECISION AS VARCHAR(30)) ||
CASE
WHEN NUMERIC_SCALE = 0 THEN ''
ELSE ',' || CAST(NUMERIC_SCALE AS VARCHAR(3))
END
ELSE ''
END || ')'
END || ',' "SQLCOL",
COLUMN_NAME,
DATA_TYPE, CHARACTER_MAXIMUM_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE, ORDINAL_POSITION
FROM SYSIBM.COLUMNS
WHERE TABLE_NAME = 'insert your table name'
AND TABLE_SCHEMA = 'insert your table schema'
ORDER BY ORDINAL_POSITION
For Netezza, I got the following query:
SELECT 0 AS ATTNUM, 'SELECT' AS SQL
UNION
SELECT ATTNUM, 'SUM(' || ATTNAME || ') AS S_' || ATTNAME || ',' AS COLMN
FROM _V_RELATION_COLUMN RC
WHERE NAME = '<table-name>'
AND FORMAT_TYPE= 'NUMERIC'
UNION
SELECT 10000 AS ATTNUM, ' 0 AS FLAG FROM ' || '<table-name>'
ORDER BY ATTNUM
Still looking how to do this across DB2 and PostgreSQL.

Why do two seemingly identical where clauses involving nulls produce different results

I'm trying to select all records that don't have a null in a particular column and it's value isn't in another table.
So this particular situation I want to get all 'Instructors' from an import table that aren't already in the Individuals table. Obviously I don't want any blank instructors. My first attempt I tried using in the where clause:
(Instructor IS NOT NULL OR Instructor <> '')
However the results still included all blank records. When I tried using
ISNULL(Instructor, '') <> ''
I got the desired result. I can't see how these two where clauses could possibly produce different results. To me it seems like ISNULL converting the value to empty string for comparison should have exactly the same outcome as comparing the column to null then to empty string. What am I missing here? I'm guessing it's to do with the oddness of null values.
Below are the full queries
SELECT * FROM [tempimporttblTrainingLog]
LEFT JOIN tblIndividual I ON [Instructor] = I.FirstName + ' ' + I.Surname
WHERE (I.FirstName + ' ' + I.Surname IS NULL) AND (Instructor IS NOT NULL OR Instructor <> '')
SELECT * FROM [tempimporttblTrainingLog]
LEFT JOIN tblIndividual I ON [Instructor] = I.FirstName + ' ' + I.Surname
WHERE (I.FirstName + ' ' + I.Surname IS NULL) AND (ISNULL(Instructor, '') <> '')
ISNULL(Instructor, '') <> '' (1)
is equivalent to
(Instructor IS NOT NULL AND Instructor <> '') (2)
not
(Instructor IS NOT NULL OR Instructor <> '') (3)
If Instructor IS NULL, (1) and (2) will return FALSE, when (3) returns TRUE.
Same for when Instructor = ''.
ISNULL(Instructor, '') <> ''
won't return blank records, and you have an OR in the
(Instructor IS NOT NULL OR Instructor <> '')
line, meaning it will return anything which isn't null as well as non blanks, did you mean to put an AND instead?

Oracle Select Query

How can I perform a select operation on two fields and view them as a single field?
ex:
I have a customer table that holds the customers data, I want to select both last_name and first_name (two different fields) and want to view them like this, "last_name, first_name"
using the oracle command not using any language.
SELECT last_name || ', ' || first_name full_name
FROM tbl
Try this -
SELECT '"' || last_name || ',' || first_name || '"' from table