SQL Database Systems - sql

I have three Boolean Attributes in my Relation and I want only one of them to have true value or the table should give an error. How Can I do that?

You can use a check constraint, if your DBMS supports them (most of them do). In it you check, that exactly one of the flags is true. For that you can use a Boolean expression.
CREATE TABLE elbat
(...
CHECK (flag1 = true
AND flag2 = false
AND flag3 = false
OR flag1 = false
AND flag2 = true
AND flag3 = false
OR flag1 = false
AND flag2 = false
AND flag3 = true));
(Just to get the idea, syntax may vary from DBMS to DBMS.)

You can use a check constraint for that.
create table some_table
(
flag1 boolean not null,
flag2 boolean not null,
flag3 boolean not null,
constraint only_one_true
check ( (flag1,flag2,flag3) IN ( (true, false, false),
(false, true, false),
(false, false, true)) )
);
The above is standard SQL.
Some DBMS system also allow casting a boolean to a number representing 0 or 1 in that case you can just add them and the sum must be equal to 1 (ensuring that exactly one flag is set to true)
create table some_table
(
flag1 boolean not null,
flag2 boolean not null,
flag3 boolean not null,
constraint only_one_true
check ( cast(flag1 as integer) +
cast(flag2 as integer) +
cast(flag3 as integer) = 1 )
);

Related

Using if statement in string_agg function - postreSQL

The query is as follows
WITH notes AS (
SELECT 891090 Order_ID, False customer_billing, false commander, true agent
UNION ALL
SELECT 891091, false, true, true
UNION ALL
SELECT 891091, true, false, false)
SELECT
n.order_id,
string_Agg(distinct CASE
WHEN n.customer_billing = TRUE THEN 'AR (Customer Billing)'
WHEN n.commander = TRUE THEN 'AP (Commander)'
WHEN n.agent = TRUE THEN 'AP (Agent)'
ELSE NULL
END,', ') AS finance
FROM notes n
WHERE
n.order_id = 891091 AND (n.customer_billing = TRUE or n.commander = TRUE or n.agent = TRUE)
GROUP BY ORDER_ID
As you can see there are two records with order_id as 891091.
First 891091 record has commander and agent set as true
Second 891091 record has customer_billing set as true
Since switch case is used, it considers only the first true value and returns commander and does not consider agent.
So the output becomes
order_id finance
891091 AP (Commander), AR (Customer Billing)
dbfiddle.uk Example
I need all the true values in the record to be considered so that the output becomes
order_id finance
891091 AP (Commander), AP (Agent), AR (Customer Billing)
My initial thought is that using if statement instead of case statement may fix this. I am not sure how to do this inside string_agg function
How to achieve this?
EDIT 1:
The answer specified below works almost fine. But the issue is that the comma separated values are not distinct
Here is the updated fiddle
https://dbfiddle.uk/?rdbms=postgres_14&fiddle=9647d92870e3944516172eda83a8ac6e
You can consider splitting your case into separate ones and using array to collect them. Then you can use array_to_string to format:
WITH notes AS (
SELECT 891090 Order_ID, False customer_billing, false commander, true agent UNION ALL
SELECT 891091, false, true, true UNION ALL
SELECT 891091, true, true, false),
tmp as (
SELECT
n.order_id id,
array_agg(
ARRAY[
CASE WHEN n.customer_billing = TRUE THEN 'AR (Customer Billing)' END,
CASE WHEN n.commander = TRUE THEN 'AP (Commander)' END,
CASE WHEN n.agent = TRUE THEN 'AP (Agent)' END
]) AS finance_array
FROM notes n
WHERE
n.order_id = 891091 AND (n.customer_billing = TRUE or n.commander = TRUE or n.agent = TRUE)
GROUP BY ORDER_ID )
select id, array_to_string(array(select distinct e from unnest(finance_array) as a(e)), ', ')
from tmp;
Here is db_fiddle.

What is the Purpose of the IsNull in this query?

I have a desktop application that I am converting to web and I am having trouble understanding the purpose of the IsNull parts of the query. The query is for Ms SQL and I know it has a IsNull function but this is not it. So I'm confused as to it's purpose. Below is my query:
UPDATE tb_category
SET
Email = #Email,
CandidateID = #CandidateID,
Code = #Code,
TestDate = #TestDate,
Description = #Description,
PointsEarned = #PointsEarned,
PointsAvailable = #PointsAvailable,
Average25th = #Average25th,
Average75th = #Average75th,
ImportedDate = #ImportedDate,
CreationDate = #CreationDate,
TestNum = #TestNum,
CategoryNum = #CategoryNum
WHERE ((Email = #Original_Email)
AND (CandidateID = #Original_CandidateID)
AND (Code = #Original_Code)
AND (TestDate = #Original_TestDate)
AND ((#IsNull_Description = 1 AND Description IS NULL) OR (Description = #Original_Description))
AND (PointsEarned = #Original_PointsEarned)
AND ((#IsNull_PointsAvailable = 1 AND PointsAvailable IS NULL) OR (PointsAvailable =
#Original_PointsAvailable))
AND ((#IsNull_Average25th = 1 AND Average25th IS NULL) OR (Average25th = #Original_Average25th))
AND ((#IsNull_Average75th = 1 AND Average75th IS NULL) OR (Average75th = #Original_Average75th))
AND ((#IsNull_ImportedDate = 1 AND ImportedDate IS NULL) OR (ImportedDate = #Original_ImportedDate))
AND ((#IsNull_CreationDate = 1 AND CreationDate IS NULL) OR (CreationDate = #Original_CreationDate))
AND (TestNum = #Original_TestNum)
AND (CategoryNum = #Original_CategoryNum));
I tried simplifying the update statement by removing the IsNull sections but that did not work.
In SQL null is not equal (=) to anything—not even to another null, so in your query in case if both values are null (old and new one) you need to take that into account and check values with IS NULL.
I'm seeing this pattern repeated several times in the WHERE clause:
#IsNull_Description = 1 AND Description IS NULL
It means that a variable, #IsNull_SomeColumnName, which is presumably set earlier in the code, has a value of 1, and the column that the variable relates to is currently NULL.
The function IsNull(Param1, Param2) is used to substitute the value of the second parameter for the value of the first parameter if the first parameter IS NULL, and the function returns the value of Param2.
In SQL Server, and quite a few other RDBMSs, the IS NULL syntax is used to check if a value is currently NULL. Here, Description IS NULL will return TRUE if, well, Description is null, and FALSE if it is not.

IF Column has a value

I need to write sql query to check whether the column y in a table x has a value. In python I can check that like
object.y = 1
if object.y:
<statements>
Like this I need to check in Postgres
this is my query:
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang = NULL and y is TRUE order by sequence""",([event_root]))
Here I need to check y has a value.
try this
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang = NULL and coalesce(y, FALSE) is TRUE order by sequence""",([event_root]))
This is my solved answer
request.cr.execute(""" select * from x where parent_id = %s and nav_include = true and website_published = true and cms_lang is NULL and y is not null order by sequence""",([event_root]))
reference: https://www.techonthenet.com/postgresql/is_not_null.php

Return True if specific value exists in table - sql

I want to create an SQL query that will return True if a specific value exists in a specific column; if not, then it will return False.
I know that I can create something like 'SELECT something FROM somewhere WHERE something'. In this case I don't want to select anything, just to check.
My question is how can I do it.
You can use the IIf function:
SELECT IIf(something = 'Some value', True, False) FROM somewhere;
In Access, you can use a DCount expression to count the number of rows where your something field contains 'some value'. Here is an example copied from the Immediate window:
Debug.Print DCount("*", "somewhere", "something='some value'")
1
Debug.Print DCount("*", "somewhere", "something='BOGUS'")
0
You could adapt that to give you True when the count is greater than zero or False for count of zero:
Debug.Print (DCount("*", "somewhere", "something='some value'") > 0)
True
Debug.Print (DCount("*", "somewhere", "something='BOGUS'") > 0)
False
If you want to do it from a query, this one will return -1 for True and zero for False:
SELECT (DCount("*", "somewhere", "something='some value'") > 0) AS value_exists;
Or you could use a Format expression to display those values as strings: "True"; or "False":
SELECT Format(DCount("*", "somewhere", "something='some value'") > 0, 'True/False') AS value_exists;
As the name implies, DLookup is for this:
SomevalueExists = Not IsNull(DLookup("Id", "somewhere", "somefield = somevalue"))
try this:
select case when x is null then false else true end
from (select max(somecol) x
from sometable
where somecol = somevalue) a
just use
select count(*) from tableName where columnName = '$variableInput';
if you plan on reusing this you might as well make it a prepared statement that you can call upon through whichever interface you design to work with your database. If the returned value is greater than zero you know it to be true, for instance
if(preparedStatement($variableInput)>0)
{
$flag = true;
}
else
{
$flag = false;
}

Optional conditions in postgreSQL query

I need to create a procedure with optional arguments and use them only if they are not null
My current query looks like:
SELECT * FROM sth WHERE
(arg1 IS NULL OR sth.c1 = arg1) AND
(arg2 IS NULL OR sth.c2 = arg2) AND
(arg3 IS NULL OR sth.c3 > arg3) AND
(arg4 IS NULL OR sth.c4 < arg4)
I'm thinking of a way to make it look better / shorter. My first shot is:
SELECT * FROM sth WHERE
COALESCE(sth.c1 = arg1, 't') AND
COALESCE(sth.c2 = arg2, 't') AND
COALESCE(sth.c3 > arg3, 't') AND
COALESCE(sth.c4 < arg4, 't');
but I'm not sure if this looks any better. Do you know any useful tricks for this?
Keep it the way it is. Using coalesce will prevent the query planner from doing its job properly, and you'll end up with sucky query plans.
Best I'm aware, the following expressions will use a btree index:
col = 'val'
col is null
The following expressions will not use a btree index:
col is [not] 'val'
(col = 'val') is [not] <true | false | null>
col is [not] distinct from 'val'
coalesce(col, 'val') = 'val'
coalesce(col = 'val', <true | false | null>)
Ok, I think that this query is the best idea for this purpose
SELECT * FROM sth WHERE
NOT (sth.c1 = arg1) IS FALSE AND
NOT (sth.c2 = arg2) IS FALSE AND
NOT (sth.c3 > arg3) IS FALSE AND
NOT (sth.c4 < arg4) IS FALSE;
it doesn't use any functions so the query planner should work fine just as before
it just uses simple expressions where:
1.
true = true // true
true = false // false
true = null // null
2.
false is false // true
true is false // false
null is false // false
3.
not true // false
not false // true
so it will return true if expression is true OR null