How do I do a case sensitive comparison in sql? - sql

Just started a tutorial in SQL for beginners. I'm doing some exercises now and I would like to know how to change the title.
If you look at here: you'll see that I have made firstname, lastname, title, age and salary. And I wrote the letters in small letter.
How can I change it to capital letter?
http://tinypic.com/r/amtpgm/3
I tried using this:
update mytablename
set firstname = 'Firstname'
where firstname = 'firstname'
But I later realized that this one will not work.
Thanks
====
additional question:
I also notice that if I wrote with spaces, then its not recognized. It's the first part only which will be displayed. Do you know why is it doing? Thanks
create table myemployees_tr0214
(First Name varchar(20),
Last Name varchar(20),
Title char(5),
Age number(3),
Salary number(6,10));
==========
thank you for all your inputs.
I've tried this one in renaming the "Firstname" to "Fname" and it didn't work. Did I miss something?
alter table myemployees_tr0214
rename column Firstname to Fname;

This should update all the firstnames in the table to an uppercase first letter:
UPDATE mytablename SET firstname = CONCAT(UCASE(MID(firstname,1,1)),MID(firstname,2));
Hope this helps you :)

First, unless you really want to change the names of the fields, don't. It's not really all that important if all you're doing is learning SQL. Note that if you want to learn the syntax for doing so, then of course it would be a worthwhile exercise, but other than that, I'd let it be.
Your edited question mentions using spaces in names. This is not allowed. The rules for what constitutes a "SQL Identifier", be it the name of a table, column, constraint, etc. has some strict rules, and simplified they are that you should only use letters, underscores, and digits, except that you can't start with a digit.
Now, why the online website that you're using to learn SQL through doesn't complain when you add those spaces, that I don't know, and to me that makes it a little suspect. It doesn't sound as though it actually uses a known database engine, as just the presence of those spaces there + the extra words would make any normal database engine complain about bad syntax.
In order to fix it, either add underscores instead of spaces, or contract and use camelCasing, like this: FirstName, LastName

Ah, there are two ways to read this question. The first is based on reading the sample UPDATE you posted. This will fail because SQL by default doesn't do a case sensitive comparison on strings.
The second piece of code implies what you wanted was to ALTER TABLE and change the name of the column from a column name with one casing to another. In MS-SQL, you can't do that without dropping the whole table and re-creating it, in other dialects of SQL there will be version specific DDL syntax.
And finally, in MS-Access, if a column name has a space, you wrap it in double quotes, e.g. "My Column" in SQL wrap it in [My Column]

update mytablename set firstname = 'Firstname'; where firstname = 'firstname';
This will update the values of the firstname column. What you are trying to do is change the name of the firstname column. How to do this depends on the database you're using (which you haven't mentioned).
If it's MS Access or SQL server, you can open the table in the UI and use the designer to change the column name.
Otherwise you can use the SQL ALTER TABLE statement, as described here.

For MS SQL Server...
You'd use [ and ] to delimit identifiers:
create table myemployees_tr0214 (
[First Name] varchar(20), --here
[Last Name] varchar(20), --here
Title char(5),
Age number(3),
Salary number(6,10)
);
If you want to change the column name from "firstname" to "Firstname", you could use sp_rename in MS SQL Server.
If you want to change the first letter of the data in the "firstname" column, other posters have offered solutions and here's another for a single name.
update mytablename
set firstname = 'Firstname'
where firstname COLLATE Latin1_general_Bin = 'firstname' COLLATE Latin1_general_Bin

If you're using mysql see: http://dev.mysql.com/doc/refman/5.0/en/charset-binary-op.html
The BINARY operator casts the string
following it to a binary string. This
is an easy way to force a comparison
to be done byte by byte rather than
character by character. BINARY also
causes trailing spaces to be
significant
mysql> SELECT 'a' = 'A';
-> 1
mysql> SELECT BINARY 'a' = 'A';
-> 0
mysql> SELECT 'a' = 'a ';
-> 1
mysql> SELECT BINARY 'a' = 'a ';
-> 0

you'll need some kind of unique row indentifier like id so you can do
update mytablename set firstname = 'Firstname' where id = 1
now what can be used as a unique row indentifier is a huge debate of natural vs surrogate keys. use what you think is best for your example but i'm a supporter of surogate keys since every natural key has the possibility to change.

This may need to be optimize for more but it will allow you to even update mulitple first name MSSQL version
select 'mary ellen' as firstname into #test
insert into #test select 'Nathan'
select
Case when patindex('% %',firstname) >0 then
upper(left(firstname,1)) --first letter
+ rtrim(substring(firstname,2,patindex('% %',firstname)-1)) --whole firstname
+ ' ' -- space
+ Upper(substring(firstname,patindex('% %',firstname)+1,1)) --first letter last name
+ rtrim(substring(firstname,patindex('% %',firstname)+2, len(firstname)))
else
upper(left(firstname,1)) + substring(firstname,2,len(firstname))
end as firstname
from #test
update #test
set firstname = Case when patindex('% %',firstname) >0 then
upper(left(firstname,1)) --first letter
+ rtrim(substring(firstname,2,patindex('% %',firstname)-1)) --whole firstname
+ ' ' -- space
+ Upper(substring(firstname,patindex('% %',firstname)+1,1)) --first letter last name
+ rtrim(substring(firstname,patindex('% %',firstname)+2, len(firstname)))
else
upper(left(firstname,1)) + substring(firstname,2,len(firstname))
end

Related

SQL Concatenate column values and store in an extra column

I am using SQL Server 2019 (v15.0.2080.9) and I've got a simple task but somehow I am not able to solve it...
I have a little database with one table containing a first name and a last name column
CREATE TABLE [dbo].[person]
(
[first_name] [nchar](200) NULL,
[last_name] [nchar](200) NULL,
[display_name] [nchar](400) NULL
) ON [PRIMARY]
GO
and I want to store the combination of first name with an extra whitespace in between in the third column (yes I really have to do that...).
So I thought I might use the CONCAT function
UPDATE [dbo].[person]
SET display_name = CONCAT(first_name, ' ', last_name)
But my display_name column is only showing me the first name... so what's wrong with my SQL?
Kind regards
Sven
Your method should work and does work. The issue, though is that the data types are nchar() instead of nvarchar(). That means they are padded with spaces and the last name is starting at position 201 in the string.
Just fix the data type.
In addition, I would suggest that you use a computed column:
alter table person add display_name as (concat(first_name, ' ', last_name));
This ensures that the display_name is always up-to-date -- even when the names change.
Here is a db<>fiddle.
As a note: char() and nchar() are almost never appropriate. The one exception is when you have fixed length strings, such as state or country abbreviations or account codes. In almost all cases, you want varchar() or nvarchar().

Postgresql query to search by first and last name, what indexes should I create?

I'm using this query to search by "first and last name" or by "last and first name":
SELECT
"id",
"firstname",
"lastname"
FROM
"plyers"
WHERE
lower( REPLACE ( CONCAT ( lastname, firstname ), ' ', '' ) ) LIKE '%joh%'
OR
lower( REPLACE ( CONCAT ( firstname, lastname ), ' ', '' ) ) LIKE '%joh%'
ORDER BY "id" DESC
GIVEN THAT
I'm using Postgresql 13
User can search with "John Belushi" or "Belushi John" or "lushi" or "lushi jo"
The search text (joh in this case) is always lowered() and cleaned of every space: before, during and after each word. E.g. if I write " lushi JO " the final search text is: "lushijo"
This query is used A LOT to search for players in a list and for the automatic completion of some selects
QUESTIONS
Do you think it's a good query?
Do you think there is a way I can avoid CONCAT(lastname,firstname) and CONCAT(firstname,lastname)?
What indexes should I create? I read this: https://stackoverflow.com/a/2709967/10088259 but I didn't quite understand how to use it.
Use generated columns, and put indices on those.
ALTER TABLE test
ADD COLUMN first_last text GENERATED ALWAYS AS (lower(REPLACE(first || last, ' ', ''))) STORED;
CREATE INDEX IF NOT EXISTS players_first_last_idx ON test USING gin (first_last gin_trgm_ops);
ALTER TABLE test
ADD COLUMN last_first text GENERATED ALWAYS AS (lower(REPLACE(last || first, ' ', ''))) STORED;
CREATE INDEX IF NOT EXISTS players_first_last_idx ON test USING gin (last_first gin_trgm_ops);
Now the WHERE clause will be able to use the indices:
SELECT
"id",
"firstname",
"lastname"
FROM
"plyers"
WHERE
first_last LIKE '%joh%'
OR
last_first LIKE '%joh%'
ORDER BY "id" DESC
Good explanation of creating indices for LIKE queries: https://niallburkley.com/blog/index-columns-for-like-in-postgres/
Let me answer using an "Answer" instead of a "Comment" ...
If you want to allow for the versatility that you suggest -
A fast data access - taking advantage of any existing indexes, is only possible if you allow for a case-sensitive search argument for the start of the string. My biggest tables of this type were never in PostreSQL, but in 3 or 4 other brands. But all of them, when using an index, did better with WHERE fname >='Johnny' AND fname < 'Johnz' than with WHERE NAME LIKE 'Johnny%'. I actually once coded a front-end to do that change for me ...
It helps, if you can, to actually add a column fullname VARCHAR(128) DEFAULT firstname||' '||lastname to your table (length guessed as about double the length of firstname and lastname - keep it as short as you can afford without truncating the strings.
Add non-unique one-column indexes for firstname, lastname, and your new fullname.
Finally, be frank and open to the end users, telling them that an "begins-with" predicate will always be considerably faster than a "contains" predicate - let alone a case insensitive predicate.
If your front-end is a normal SQL client, the end-user must code their queries to respect the points above.
If you build your own front-end application, allow in the search functionality for "is equal to, case sensitive", "begins with. case sensitive" and a comparison with firstname, lastname, and, if it makes sense, fullname - as the preferred search method, but then also for "contains", "begins-with" - "is ''equal'' to" and "contains", all case insensitive - but with a warning, in the dialogue or the docu, that these latter ones are much slower.

SQL - find rows with values that has 2 spaces or more in between

I have sql table with name and surname. Surname is in own column. The problem is with users with two surnames, because sometimes they add more than one space between surnames and then I have to find and fix them manualy.
How to find these surnames with more than one space in between?
If you want to find records which have more than one space then you can use the following trick:
SELECT surname
FROM yourTable
WHERE LENGTH(REPLACE(surname, ' ', '')) < LENGTH(surname) - 1
This query will detect two or more spaces in the surname column. If you want to also do an UPDATE this is possible, but it would be fairly database-specific, and you did not specify your database as of the time I wrote this answer.
First remove those extra spaces. Then add a constraint that makes sure it doesn't happen again:
alter table tablename add constraint surname_verify check (surname not like '% %')
(Or, even better, have a trigger making sure the surnames are properly spaced, cased etc.)
How to remove extra spaces? Depends on the dbms.
You can perhaps do something like:
update tablename set surname = replace(surname, ' ', ' ')
where surname like '% %'
The where clause isn't needed, but makes the transaction much smaller.
(Iterate to get rid of triple or more spaces.) Or use regexp_replace.
Even tidier:
select string = replace(replace(replace(' select single spaces',' ','<>'),'><',''),'<>',' ')
Output:
select single spaces

Add a Column that Represents a Concatenation of Two Other Varchar Columns

I have an employees table and I want to add a third column valued as the concatenation of the first and last name called "FullName". How can I accomplish that without losing any data from either of the first two columns?
Quick preface: this answer was based on the originally incorrect tag that this question was relating to SQL Server. I'm no longer aware of its validity on Oracle SQL Developer.
ALTER TABLE Employees ADD FullName AS (FirstName + ' ' + LastName)
Although in practice I'd advise that you do that operation in your SELECT. That's somewhat personal preference, but I tend to think doing things in your end queries is a bit cleaner, more readable, and easier to maintain than storing extra, calculated columns.
Edit:
This was eventually found as the answer, and listed by the OP as a comment on this post. The following is appropriate syntax for Oracle Sql Database.
ALTER TABLE emps MODIFY (FULL_NAME VARCHAR2(50) GENERATED ALWAYS AS (first_name || ' ' || last_name) VIRTUAL);
If you need fullname column all time when you select from database then you can create computed column at the time of creation of your table employee.
for example:
CREATE TABLE Employee
(
FirstName VARCHAR(20),
LastName VARCHAR(20),
FullName AS CONCAT(FirstName,' ',LastName)
)
INSERT INTO Employee VALUES ('Rocky','Jeo')
SELECT * FROM Employee
Output:
FirstName LastName FullName
Rocky Jeo Rocky Jeo
It depends on your purpose, whether you really need to add a new column to your database, or you just need to query out the "full name" on an as-needed basis.
To view it on the fly, just run the query
SELECT firstname + ' ' + lastname AS FullName FROM employees
Beyond that, you also can create a simple Stored Procedure to store it.
(For single result use equal to in the where condition)
select *
from TABLE_name
where (Column1+Column2) in (11361+280,11365+250)
In addition to #Jacky 's answer, if you are trying to add this to a query and not the table, there is also the CONCAT() function that you can use in the select statement
SELECT CONCAT(FirstName, ' ', LastName) as FullName
FROM table_name

Handling missing columns in MySQL

Working on parsing a bunch of databases put together in an older, more freewheeling time into a new schema. Basically it's one database per year, with database names like foo98, foo99, foo2000, etc.
So for the most recent foo data, I can do something like
SELECT foo_person.mdname AS middle_name,
...
FROM foo_person, foo_place, foo_thing
As you get back into earlier versions of the foo database, middle name isn't stored. I've tried to build a kind of universal query, something like:
SELECT IFNULL(foo_person.mdname, "") AS middle_name,
...
FROM foo_person, foo_place, foo_thing
but MySQL complains about unknown column foo_person.mdname, which is entirely reasonable as it doesn't exist.
Is there some way to handle non-existent columns with just MySQL syntax, or will I have to write database-specific import queries?
There isn't any way of handling a non-existent column in sql (as opposed to an empty column).
You can tell whether the column is there or not using the information_schema tables, like so:
select * from information_schema.columns
where table_name='mytable' and table_schema='mydatabase';
Yes there is a way.
Let's consider these databases
DB2009 has Person with Fname, MInitial and LName
DB2008 has Person with Fname and LName
DB2007 has Person with PersonName
You can do something similar the following (I wrote this for MS SQL Server)
/*all three columns exist*/
SELECT FName, MInitial, LName
From DB2009.Person
UNION
/*one column is a forced null */
SELECT FName, NULL as MInitial, LName
From DB2008.Person
UNION
/*two columns are derived and one column is a forced null */
SELECT SubString (1, CharIndex (PersonName, ' '), PersonName) as FirstName,
NULL as MInitial,
SubString (CharIndex (PersonName, ' '), len (PersonName), PersonName),
From DB2007.Person
Could you rename the tables and create views in their place with the missing columns?
Not sure if this is what you're looking for, but thought I would suggest it.
-- Here is your original table
create table t (fname varchar(30), lname varchar(30));
-- Rename it to something else
alter table t rename to tOrig;
-- Create a view with the columns its missing that you need
create view t as select fname, lname, '' as mname from tOrig;
If you're working with heterogenous databases, I would use database-specific import queries anyways. You might need to join some columns and remove some, and truncate some, etc.
Instead of making more complex sql queries, perhaps it would be better to
alter the foo98 and foo99 tables to add in the missing columns.
For example, to add a column of type varchar(30) called "mdname" to foo98:
ALTER TABLE foo98 ADD mdname varchar(30) AFTER first_name;
Then you can relax and use the same simple SQL query no matter which tabel is being accessed.