How AND/OR operators works? [duplicate] - sql

This question already has answers here:
SQL Logic Operator Precedence: And and Or
(5 answers)
Closed 4 years ago.
I'm Reading book about sql and I see some statements using or/and and I don't understand them:
this is the main statement:
SELECT ∗
FROM administrators
WHERE username = ’’ AND password = ’’;
if some one try to do an sql bypass , he will do this:
SELECT ∗
FROM administrators
WHERE username = ” OR ‘1’=‘1’ AND password = ”;
or this
SELECT ∗
FROM administrators
WHERE (username = ’’) OR (‘1’=‘1’ AND password = ’’);
how these 2 statements get the same results, I don't understand how AND/OR works in theses statements ..
and the last question how these statements return all value in database (bypass the auth):
select *
from users
where (username = '') or (1=1) or (1=1 AND password = '') ;
OR
SELECT ∗
FROM administrators
WHERE username = ’’ AND
password = ’’ OR
1’=‘1’;

In simple explanations:
SELECT ∗ FROM administrators WHERE username = ” OR ‘1’=‘1’ AND password = ”;
Here if the username exists and password is wrong, it will return all columns for that username else returns nothing.
SELECT ∗ FROM administrators WHERE (username = ’’) OR (‘1’=‘1’ AND password = ’’);
This returns the same thing as the above, the brackets don't matter.
SELECT ∗ FROM administrators WHERE username = ’’AND password = ’’ OR ‘1’=‘1’ ;
This makes a difference, even if both username and password are wrong, it will return the full * columns. [best option for a SQL injection for full table data]
select * from users where (username = '') or (1=1) or (1=1 AND password = '') ;
same results as above
Its easy to think of it this way:
any AND/OR condition introduced after where is paired for the first constraint, any other introduced after that is a constraint of its own.
WHERE condition1 OR/AND condition1-pair AND separate condition

You can consider AND as multiplication, OR as addition, true statement as 1 and false statement as 0. For example statement
SELECT .... WHERE y = 0 AND x < 1 OR 1 = 1
will always be true, because
1*1 + 1 = 1
0*0 + 1 = 1
1*0 + 1 = 1
(0 and 1 are Boolean, not decimal)

Related

GETTING ERROR-- ORA-00936:MISSING EXPRESSION for below query please help on this

SELECT CASE (SELECT Count(1)
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(
SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988')
)
WHEN 0 THEN
(
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27' )
WHEN 1 THEN
(
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
ELSE NULL
END
FROM dual;
You need to recreate your query and make sure to follow the flow of the clauses properly, please check the next two links to get a better understanding :
[ORA-00936: missing expression tips]
How do I address this ORA-00936 error?
Answer: The Oracle oerr utility notes this about the ORA-00936 error:
ORA-00936 missing expression
Cause: A required part of a clause or expression has been omitted. For example, a SELECT statement may have been entered without a list of columns or expressions or with an incomplete expression. This message is also issued in cases where a reserved word is misused, as in SELECT TABLE.
Action: Check the statement syntax and specify the missing component.
The ORA-00936 happens most frequently:
1 - When you forget list of the column names in your SELECT statement.
2. When you omit the FROM clause of the SQL statement.
ora-00936-missing-expression
I hope this can help you.
You cannot use a simple select query like this. You have to use a PL/SQL block like below -
DECLARE NUM_CNT NUMBER := 0;
BEGIN
SELECT Count(1)
INTO NUM_CNT
FROM wf_item_activity_statuses_v t
WHERE t.activity_label IN ('WAITING_DISB_REQ',
'LOG_DDE',
'LOG_SENDBACK_DDE')
AND t.item_key IN(SELECT r.i_item_key
FROM wf_t_item_xref r
WHERE r.sz_appl_uniqueid = '20400000988');
IF NUM_CNT = 0 THEN
delete
from t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_item_key = '648197'
AND p.i_document_srno = '27';
ELSIF NUM_CNT = 1 THEN
DELETE
FROM t_col_val_document_uploaded p
WHERE p.sz_application_no = '20400000988'
AND p.sz_collateral_id = 'PROP000000000PRO1701'
AND p.i_document_srno = '28' )
END IF;
END;

Postgres generate a unique username

I have a requirement where I need to generate to unique usernames. I know how I would do it server side but want to make it as efficient as possible and do it on the database as part of a procedure but unsure where to start as I don't work with SQL too often.
I want to be able to create a username using the first letter of their forename and their surname plus some numbers and if a user already exists with that username then update it by 1. e.g.
I have users
Bob Jones bjones1
Bill Jones bjones2
If a user Beatrice Jones is added then that will be bjones3.
However users can choose to pick their username so someone may have already chosen bjones3 so I want it to automatically generate bjones4.
If there are no user B Jones then the first username created should be bjones
Ideally this would all happen as part of the user insert into the database so my Go code just executes a single database call and the user gets inserted.
Update:
When a user chooses their own username I check if it exists and block them from using it if it exists.
Hmmm . . . I think this will do:
select 'bjones' || coalesce(lpad( ((regexp_match(max(username), '[0-9]+$'))[1]::int + 1)::text, 5, '0'), '00000')
from t
where username ~ '^bjones[0-9]{5}$';
Here is a db<>fiddle.
More strict and parameterized, with 4-digit sequential number.
with
unp as -- user name prefix
(select left(lower(:givenname), 1) || lower(:surname) unp),
maxno as -- max existing seq.number for this username prefix
(
select coalesce(max((regexp_match(username, '(\d+)$'))[1]::integer), 0) maxno
from usernames
where username ~ ('^'||(select unp from unp)||'\d+$')
)
select (select unp from unp) || to_char((select maxno + 1 from maxno), 'FM0009') username;
I did something similar with the following code:
_username = left(lower(_firstname), 1) || lower(_lastname);
PERFORM id FROM users WHERE username = _username;
IF FOUND THEN
FOR i in 1 .. 999
LOOP
_username := _username || i;
PERFORM id FROM users WHERE username = _username;
IF NOT FOUND THEN
EXIT;
END IF;
END LOOP;
END IF;

WHERE [Expression] = TRUE/FALSE in SQL Server

I have a situation where I'm trying to filter people that have credits or not. Here's an example Dapper query for reference:
var sql = #"
SELECT *
FROM Person
WHERE (Person.Credits > 0) = #hasCredits";
Connection.Query(sql, new { hasCredits });
I was pretty sure Postgres allows you to do this, hence my surprise when on SQL Server this failed with Incorrect syntax near '='.
With the sample data below, I would expect the query to return the Person with the ID of 1 when hasCredits is FALSE and the Person with the ID of 2 when hasCredits is TRUE.
INSERT INTO Person (PersonId, Credits) VALUES (1, 0), (2, 0);
In SQL Server Is there a way to evaluate whether an expression evaluates to true or false?
I've considered the following (horrible looking) options, but was hoping there was a more elegant solution:
"WHERE (Person.Credits " + (hasCredits ? ">" : "=") + " 0)"
"WHERE (#hasCredits = 1 AND Person.Credits > 0) OR (#hasCredits = 0 AND Person.Credits = 0)"
Considering that when Has credits radio button is selected #hasCredits variable will have 1 else when Doesn't have credits is selected #hasCredits variable will have 0 else #hasCredits variable will be null
SELECT *
FROM Person
WHERE (Person.Credits > 0 and #hasCredits=1) or --Has credits
(Person.Credits <1 and #hasCredits=0) or --Doesn't have credits
(#hasCredits IS NULL) --Don't care
You question was quite plain and the answer is super easy!
case when Person.Credit > 0 then 1 else 0 end = #hasCredits

SQL function not working properly, but does when not as a function

I'm having another issue with a SQL Function that I had written. If I run it not in a function and use declared variables, then it works perfectly. But as soon as I put it into a function and run it, nothing appears, its empty.
I cannot put this into a stored procedure, it needs to be in a function.
the code is
select * from [MYTABLE]
where MajorGroupID = #MajorGroupID
and ((#Status = 0 and (
Inactive = 0)
))
or MajorGroupID = #MajorGroupID and (#Status = 1 and (Inactive = 0 or Inactive = 1))
I am not really familiar with functions, I can do basic things with functions but when it comes to adding logic to it. If I was allowed to use stored procedures then I wouldn't be having problems.
This is MSSQL and using SQL Server 2010.
EDIT, Added complete function
CREATE FUNCTION [dbo].[WT_FN_GET_MYTABLE_By_MajorGroupID_Inactive]
(
#MajorGroupID varchar,
#Status int
)
RETURNS TABLE
AS
RETURN
select * from [MYTABLE]
where MajorGroupID = #MajorGroupID
and ((#Status = 0 and (
Inactive = 0)
))
or MajorGroupID = #MajorGroupID and (#Status = 1 and (Inactive = 0 or Inactive = 1))
You don't provide a length for #MajorGroupID varchar, so it is going to be 1 by default, at which point it will not find anything in the table.
Provide a length, e.g. #MajorGroupID varchar(30).

Nhibernate Criteria Conditional Where

Im working on a NHibernate criteria wich i graduatly builds upp depending on input parameters.
I got some problem with the postal section of these paramters.
Since we got a 5 number digit zipcodes the input parameter is a int, but since we in database also accept foreign zipcodes the database saves it as string.
What im trying to replicate in NHibernate Criteria/Criterion is the following where clause.
WHERE
11182 <=
(case when this_.SendInformation = 0 AND dbo.IsInteger(this_.Zipcode) = 1 then
CAST(REPLACE(this_.Zipcode, ' ', '') AS int)
when this_.SendInformation = 1 AND dbo.IsInteger(this_.WorkZipcode) = 1 then
CAST(REPLACE(this_.WorkZipcode, ' ', '') AS int)
when this_.SendInformation = 2 AND dbo.IsInteger(this_.InvoiceZipcode) = 1 then
CAST(REPLACE(this_.InvoiceZipcode, ' ', '') AS int)
else
NULL
end)
What we do is to check where the member contact (this_) has preferenced to get information sent to, then we check the input zipcode as integer against three different columns depending on if the column is convertable to int (IsInteger(expr) function) if column is not convertable we mark the side as NULL
in this case we just check if the zipcode is >= input parameter (reversed in sql code since paramter is first), the goal is to do a between (2 clauses wrapped with 'AND' statement), >= or <=.
UPDATE
Got a hint of success.
Projections.SqlProjection("(CASE when SendInformation = 0 AND dbo.IsInteger(Zipcode) = 1 then CAST(REPLACE(Zipcode, ' ', '') AS int) when SendInformation = 1 AND dbo.IsInteger(WorkZipcode) = 1 then CAST(REPLACE(WorkZipcode, ' ', '') AS int) when SendInformation = 2 AND dbo.IsInteger(InvoiceZipcode) = 1 then CAST(REPLACE(InvoiceZipcode, ' ', '') AS int) else NULL END)"
, new[] { "SendInformation", "Zipcode", "WorkZipcode", "InvoiceZipcode" },
new[] { NHibernateUtil.Int32, NHibernateUtil.String, NHibernateUtil.String, NHibernateUtil.String });
Throw my whole clause in a Projections.SqlProjection, however when i run my code some of my projection is cut (" AS int) else NULL END)" is cut from the end) and makes the sql corrupt.
Is there some kind of limit on this ?
Got it working yesterday.
Projections.SqlProjection worked, however if you don't name the projection as a column it some how cuts some of the TSQL code.
(Case
when x = 1 then 'bla'
when x = 2 then 'bla_bla'
else NULL
END) as foo
when using the last part (as foo) and naming the entire case syntax it works and dont cut anything.
However i dont know why but i could not manage to use the aliases from the other part of the criteria.