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.
Related
I have the following query:
SELECT * FROM MailingList
There are about 20+ columns in the MailingList table, one which is called Address. This column has some fields which contain commas, which I need to take out. So I updated my query to:
SELECT REPLACE(Address, ',', '') AS Address, * FROM MailingList
But now I have two Address columns. Is there a way to only display one Address column while still using the wildcard (*) for all the other columns?
There is not a way to do this, though listing the columns you want explicitly is a good idea anyway.
You can trick as following query:
Get the data into a temp table
Drop the cloumns that are not needed
Get results and drop temp table
SELECT *, REPLACE(Address, ',', '') AS Address2
INTO #TempTable
FROM MailingList
ALTER TABLE #TempTable
DROP COLUMN [Address]
SELECT * FROM #TempTable
DROP TABLE #TempTable
I agree with Shadow - avoid using the * wild card if you can...
I know listing out ALL of the columns in select statement for big tables is a pain so here is a quick short cut you may not be aware of: In SQL Server Management Studio, browse through the object explorer and find the table you want to select from (MailingList). Right-click it to view the context menu and choose "Script Table as" then "SELECT TO" then "New Query Editor Window". This will create a new select statement with each column spelled out. In the future, use this method to create select statements, queries, procedures, etc. rather then the * wildcard. Performance is better and it just looks nicer :-)
Then you can solve your alias issue with the replace function.
How can I select the column name and table name from a SQL?
I tried something like this but it didn't work:
select column_name, table_name from (select * from users);
This might sound silly, but I have a list of different SQLs and I need to extract their columns and tables into a list. So some of the statements could me:
select username, password from users
select createdate from userlog
select * from dept
...
If I can select the column name and table name of a select statement, then I should get, say for the first statement, username and password for columns and users for table name. And createdate for column and userlog for table name in the second statement.
Then if it all works, I can then loop through the list of select statements and extract their column and table names.
The below query worked for Oracle database.
SELECT COLUMN_NAME,TABLE_NAME FROM ALL_TAB_COLUMNS
You can see more about information-schema
Edit:
You may try like this:
SELECT COLUMN_NAME,TABLE_NAME FROM ALL_TAB_COLUMNS
WHERE TABLE_NAME IN (SELECT ColumnName FROM users)
You need to parse the SQL statement so the SQL engine figures out the columns and datatypes of the columns that the statement returns.
How you do it best depends on what environment you are using. In some programming languages when you create a SqlPreparedStatement or OraCommand or whatever the object may be called, that object may have a metadata collection populated with column information after parsing.
If you are doing it in the database itself, parsing your statement with DBMS_SQL can get you the information you need. See Example 8 in the documentation at this link:
http://docs.oracle.com/database/121/ARPLS/d_sql.htm#ARPLS68205
--
Oh, and this gives you column names of the select statement. The table names I do not know of any way to get easily.
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
I want to write a query in T-SQL to perform a search on two concatenated columns. The two columns are fname and lname. Here is what I have so far:
SELECT
fname,
lname,
...
FROM
users
JOIN
othertable ON foo=bar
WHERE
fname+' '+lname LIKE '%query%'
SQL server doesn't like that syntax, though. How do I structure the query so that I can perform a WHERE LIKE operation that searches through two concatenated columns, allowing me to search the user's full name, rather than just first name and last name individually?
I can only suggest that one of fname or lname is NULL so the LIKE fails., (NULL concat anything is null)
Try
...
ISNULL(fname, '') + ' ' + ISNULL(lname, '') LIKE '%query%'
However, I would use a computed column and consider indexing it because this will run awfully.
My suggestion is to add a calculated column to your table for full_name
calculated column examples:
--drop table #test
create table #test (test varchar (10) , test2 varchar (5),[Calc] AS right(test, 3))
Insert #test
values('hello', 'Bye')
Insert #test
values('hello-bye', null)
Alter table #test
add [MyComputedColumn] AS substring(test,charindex('-',test), len(test)),
Concatenatedcolum as test+ ' ' +test2
select * from #test
As you can see you may have to play around a bit until you get the results you want. Do that in a temp table first to avoid having to restructure the database table multiple times. For names, especially if you are using middle name which is often blank, you may need to add some code to handle nulls. You may also need to have code sometimes to cast to the same datatype if one filed you are concatenating is an int for instance and the other a varchar.
I think one of the join conditions might be causing a problem. Try rewriting it, you may find the error goes away ;)
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