Обсуждение: Incorrect Query
Hi,
I'm working on an application, the user enters the customers id or their firstname or their lastname or their firstname
andlastname. The problem is when they enter their firstname AND their lastname it returns as if you had entered either
theirfirstname OR their lastname. I must be missing brackets somewhere, but I can't figure it out, I've tried
everythingI could think of, does anyone have any ideas?
Query:
select person_id, initcap(firstname), initcap(lastname), dob, street, city
from person5
where person_id = ''
or ( ( firstname = initcap('sharon') )
or ( lastname = initcap('cowling') ) )
or ( ( firstname = initcap('sharon')
and lastname = initcap('cowling') ) )
order by lastname;
Results:
person_id | initcap | initcap | dob | street | city
-----------+---------+----------+------------+---------+------------
1018 | Katrina | Cowling | 07/07/1976 | Long St | Wellington
858 | Sharon | Cowling | 16/10/1979 | A Grove | Wellington
1060 | Sharon | O'neill | 11/11/1977 | Fsddf | Fdsfds
1062 | Sharon | O'ray | 11/11/1977 | Dfs | Sfsf
1061 | Sharon | O'reilly | 11/11/1977 | Sfds | Sfdsfs
880 | Sharon | Smiley | 16/11/1979 | The St | The City
(6 rows)
sharon=> \d person5
Table "person5"
Attribute | Type | Modifier
------------------+-----------------------+----------
person_id | integer | not null
firstname | character varying(25) | not null
lastname | character varying(25) | not null
dob | date | not null
street | character varying(50) | not null
suburb | character varying(50) |
city | character varying(50) | not null
homephone | character varying(15) |
workphone | character varying(15) |
mobile | character varying(15) |
type | character varying(30) | not null
date_approved | date | not null
approved_by | character varying(50) | not null
vehicle_type | character varying(50) |
vehicle_rego | character varying(6) |
drivers_licence | character varying(10) |
firearms_licence | character varying(20) |
notes | character varying(80) |
status | character varying(10) |
Indices: firstname_idx,
fullname_idx,
lastname_idx,
person5_drivers_licence_key,
person5_firearms_licence_key,
person5_pkey
Regards,
Sharon Cowling
On Wed, 2002-05-08 at 17:06, Sharon Cowling wrote:
> Hi,
>
> I'm working on an application, the user enters the customers id or
> their firstname or their lastname or their firstname and lastname.
> The problem is when they enter their firstname AND their lastname
> it returns as if you had entered either their firstname OR their
> lastname. I must be missing brackets somewhere, but I can't figure
> it out, I've tried everything I could think of, does anyone have
> any ideas?
>
> Query:
> select person_id, initcap(firstname), initcap(lastname), dob, street, city
> from person5
> where person_id = ''
> or ( ( firstname = initcap('sharon') )
> or ( lastname = initcap('cowling') ) )
> or ( ( firstname = initcap('sharon')
> and lastname = initcap('cowling') ) )
> order by lastname;
Hi Sharon,
Several points here:
Firstly, you are presumably building this SQL in a program. You should
probably look at the values for firstname and lastname in your program,
and construct your SQL differently, as appropriate.
If that's not possible, and you have to have a static SQL string that
you replace values into, then you will want to do something like this:
SELECT ...
WHERE (firstname = '$fname' AND '' = '$lname' )
OR (lastname = '$lname' AND '' = '$fname' )
OR (firstname = '$fname' AND lastname = '$lname' )
This means that you compare firstname with $fname _only_ if $lname is
empty, and vice versa. I'll leave it to you to decide if the person_id
= '' was doing the correct thing...
Thirdly, if you don't trust your database to contain 'initcap()' values
(looking at your output specifiers), how can you compare against
initcap() values in the where clause! In the where clause you should
really be something like:
WHERE lower(firstname) = lower('$fname') ...
Cheers,
Andrew.
PS. Say "Hi" to Andrew McClure from me :-)
--
--------------------------------------------------------------------
Andrew @ Catalyst .Net.NZ Ltd, PO Box 11-053, Manners St, Wellington
WEB: http://catalyst.net.nz/ PHYS: Level 2, 150-154 Willis St
DDI: +64(4)916-7201 MOB: +64(21)635-694 OFFICE: +64(4)499-2267
Are you enrolled at http://schoolreunions.co.nz/ yet?
Hi Andrew,
Sorry I should have said the values were just examples, its a java program so
the id, firstname, and lastname are variables taken from the user entry, I left
the id blank in the example as more often than not the user will only be
entering the persons name.
The names are stored with initcap() values in the database, but when the person
is doing a search to retrieve this data they may enter the name all in lower
case, so I probably don't need initcap() in the select clause, thanks for your
advice I will look at a different way of comparing the values in my java code.
I'll say hi to Andrew for you.
Regards,
Sharon Cowling
Quoting Andrew McMillan <andrew@catalyst.net.nz>:
> On Wed, 2002-05-08 at 17:06, Sharon Cowling wrote:
> > Hi,
> >
> > I'm working on an application, the user enters the customers id or
> > their firstname or their lastname or their firstname and lastname.
> > The problem is when they enter their firstname AND their lastname
> > it returns as if you had entered either their firstname OR their
> > lastname. I must be missing brackets somewhere, but I can't figure
> > it out, I've tried everything I could think of, does anyone have
> > any ideas?
> >
> > Query:
> > select person_id, initcap(firstname), initcap(lastname), dob, street, city
>
> > from person5
> > where person_id = ''
> > or ( ( firstname = initcap('sharon') )
> > or ( lastname = initcap('cowling') ) )
> > or ( ( firstname = initcap('sharon')
> > and lastname = initcap('cowling') ) )
> > order by lastname;
>
> Hi Sharon,
>
> Several points here:
>
> Firstly, you are presumably building this SQL in a program. You should
> probably look at the values for firstname and lastname in your program,
> and construct your SQL differently, as appropriate.
>
> If that's not possible, and you have to have a static SQL string that
> you replace values into, then you will want to do something like this:
>
> SELECT ...
> WHERE (firstname = '$fname' AND '' = '$lname' )
> OR (lastname = '$lname' AND '' = '$fname' )
> OR (firstname = '$fname' AND lastname = '$lname' )
>
> This means that you compare firstname with $fname _only_ if $lname is
> empty, and vice versa. I'll leave it to you to decide if the person_id
> = '' was doing the correct thing...
>
> Thirdly, if you don't trust your database to contain 'initcap()' values
> (looking at your output specifiers), how can you compare against
> initcap() values in the where clause! In the where clause you should
> really be something like:
> WHERE lower(firstname) = lower('$fname') ...
>
> Cheers,
> Andrew.
>
> PS. Say "Hi" to Andrew McClure from me :-)
> --
> --------------------------------------------------------------------
> Andrew @ Catalyst .Net.NZ Ltd, PO Box 11-053, Manners St, Wellington
> WEB: http://catalyst.net.nz/ PHYS: Level 2, 150-154 Willis St
> DDI: +64(4)916-7201 MOB: +64(21)635-694 OFFICE: +64(4)499-2267
> Are you enrolled at http://schoolreunions.co.nz/ yet?
>
-------------------------------------------------
This mail sent through IMP: http://horde.org/imp/
Sharon,
You were abusing parentheses and confusing the issue. Don't do that, it
just makes the query less readable.
Here is what you actually wrote:
where
person_id = ''
or
(
(
firstname = initcap('sharon')
)
or
(
lastname = initcap('cowling')
)
)
or
(
(
firstname = initcap('sharon')
and
lastname = initcap('cowling')
)
)
Which is simplified to (removing parentheses where redundant but
retaining all the logic). Check out that first bit where you match on
fname or lname. That last bit doesn't even do anything since the other
name expressions covered it already.
where
person_id = ''
or
firstname = initcap('sharon')
or
lastname = initcap('cowling')
or
(
firstname = initcap('sharon')
and
lastname = initcap('cowling')
)
Why not just use?
WHERE person_id = ''
OR (firstname = initcap('sharon')
AND
lastname = initcap('cowling')
)
Hi,
> Why not just use?
>
> WHERE person_id = ''
> OR (firstname = initcap('sharon')
> AND
> lastname = initcap('cowling')
> )
>
Because the user may enter either just the firstname or just the lastname, so the above won't work if I just enter
'cowling'and there are multiple entries of 'cowling' in the database, it returns 0 rows.
select person_id, initcap(firstname), initcap(lastname), dob, street, city
from person5
where person_id = ''
OR (firstname = initcap('')
AND
lastname = initcap('cowling')
);
person_id | initcap | initcap | dob | street | city
-----------+---------+---------+-----+--------+------
(0 rows)
select person_id, initcap(firstname), initcap(lastname), dob, street, city
from person5
where
person_id = ''
or
firstname = initcap('')
or
lastname = initcap('cowling')
or
(
firstname = initcap('sharon')
and
lastname = initcap('')
)
person_id | initcap | initcap | dob | street | city
-----------+---------+---------+------------+---------+------------
1018 | Katrina | Cowling | 07/07/1976 | Long St | Wellington
858 | Sharon | Cowling | 16/10/1979 | A Grove | Wellington
Regards,
Sharon Cowling
> -----Original Message-----
> From: Joshua b. Jore [mailto:josh@greentechnologist.org]
> Sent: Thursday, 9 May 2002 01:39
> To: Sharon Cowling
> Cc: Pgsql-Novice (E-mail)
> Subject: Re: [NOVICE] Incorrect Query
>
>
> Sharon,
> You were abusing parentheses and confusing the issue. Don't
> do that, it
> just makes the query less readable.
>
> Here is what you actually wrote:
>
> where
> person_id = ''
> or
> (
> (
> firstname = initcap('sharon')
> )
> or
> (
> lastname = initcap('cowling')
> )
> )
> or
> (
> (
> firstname = initcap('sharon')
> and
> lastname = initcap('cowling')
> )
> )
>
> Which is simplified to (removing parentheses where redundant but
> retaining all the logic). Check out that first bit where you match on
> fname or lname. That last bit doesn't even do anything since the other
> name expressions covered it already.
>
> where
> person_id = ''
> or
> firstname = initcap('sharon')
> or
> lastname = initcap('cowling')
> or
> (
> firstname = initcap('sharon')
> and
> lastname = initcap('cowling')
> )
>
> Why not just use?
>
> WHERE person_id = ''
> OR (firstname = initcap('sharon')
> AND
> lastname = initcap('cowling')
> )
>
Hi,
Sorry for bothering the list, had a bad day yesterday, acheived the desired effect in Java code.
Regards,
Sharon Cowling
> -----Original Message-----
> From: pgsql-novice-owner@postgresql.org
> [mailto:pgsql-novice-owner@postgresql.org]On Behalf Of Sharon Cowling
> Sent: Thursday, 9 May 2002 08:01
> To: Joshua b. Jore
> Cc: Pgsql-Novice (E-mail)
> Subject: Re: [NOVICE] Incorrect Query
>
>
> Hi,
>
> > Why not just use?
> >
> > WHERE person_id = ''
> > OR (firstname = initcap('sharon')
> > AND
> > lastname = initcap('cowling')
> > )
> >
>
> Because the user may enter either just the firstname or just
> the lastname, so the above won't work if I just enter
> 'cowling' and there are multiple entries of 'cowling' in the
> database, it returns 0 rows.
>
>
> select person_id, initcap(firstname), initcap(lastname), dob,
> street, city
> from person5
> where person_id = ''
> OR (firstname = initcap('')
> AND
> lastname = initcap('cowling')
> );
>
> person_id | initcap | initcap | dob | street | city
> -----------+---------+---------+-----+--------+------
> (0 rows)
>
> select person_id, initcap(firstname), initcap(lastname), dob,
> street, city
> from person5
> where
> person_id = ''
> or
> firstname = initcap('')
> or
> lastname = initcap('cowling')
> or
> (
> firstname = initcap('sharon')
> and
> lastname = initcap('')
> )
>
> person_id | initcap | initcap | dob | street | city
> -----------+---------+---------+------------+---------+------------
> 1018 | Katrina | Cowling | 07/07/1976 | Long St | Wellington
> 858 | Sharon | Cowling | 16/10/1979 | A Grove | Wellington
>
> Regards,
>
> Sharon Cowling
>
>
> > -----Original Message-----
> > From: Joshua b. Jore [mailto:josh@greentechnologist.org]
> > Sent: Thursday, 9 May 2002 01:39
> > To: Sharon Cowling
> > Cc: Pgsql-Novice (E-mail)
> > Subject: Re: [NOVICE] Incorrect Query
> >
> >
> > Sharon,
> > You were abusing parentheses and confusing the issue. Don't
> > do that, it
> > just makes the query less readable.
> >
> > Here is what you actually wrote:
> >
> > where
> > person_id = ''
> > or
> > (
> > (
> > firstname = initcap('sharon')
> > )
> > or
> > (
> > lastname = initcap('cowling')
> > )
> > )
> > or
> > (
> > (
> > firstname = initcap('sharon')
> > and
> > lastname = initcap('cowling')
> > )
> > )
> >
> > Which is simplified to (removing parentheses where redundant but
> > retaining all the logic). Check out that first bit where
> you match on
> > fname or lname. That last bit doesn't even do anything
> since the other
> > name expressions covered it already.
> >
> > where
> > person_id = ''
> > or
> > firstname = initcap('sharon')
> > or
> > lastname = initcap('cowling')
> > or
> > (
> > firstname = initcap('sharon')
> > and
> > lastname = initcap('cowling')
> > )
> >
> > Why not just use?
> >
> > WHERE person_id = ''
> > OR (firstname = initcap('sharon')
> > AND
> > lastname = initcap('cowling')
> > )
> >
>
>
> ---------------------------(end of
> broadcast)---------------------------
> TIP 5: Have you checked our extensive FAQ?
>
> http://www.postgresql.org/users-lounge/docs/faq.html
>