I need to be able to check if a column exists and if it does then I want to SELECT from it.
I am trying lots of different variations but I'm not even sure if this is possible.
Here's my latest attempt:
SELECT
IF (EXISTS (SELECT `Period` AS `Period` FROM myview), `PERIOD`,
IF (EXISTS (SELECT `Country` AS `COUNTRY` FROM myview),`COUNTRY` FROM myview ;
Any ideas?
EDIT
I had seen the other question on here: MySQL, Check if a column exists in a table with SQL
But I still struggle with the if statement. I can check to see if the column exists using the answer in the question above. But my question is - how to execute a select statement from that column if the result is found to be true.
EDIT 2
The answer below indicates that I should use the BEGIN and END statement and this makes sense. However, my query complains at the first line. It says 'unexpected IF' - can anybody confirm if this is the right syntax fro MYSQL?
if( exists (SELECT *
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'db_name'
AND TABLE_NAME = 'view_name'
AND COLUMN_NAME = 'column_name') )
begin
SELECT `column_name` FROM `view_name`
end
Thanks in advance.
This query will give you whether a column exists.
SELECT *
FROM information_schema.COLUMNS
WHERE
TABLE_SCHEMA = 'db_name'
AND TABLE_NAME = 'table_name'
AND COLUMN_NAME = 'column_name'
If you want to check if some columns exist then perform a select statement you need to first check your columns exist. Then perform the select:
if (exists (SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = 'myview' AND COLUMN_NAME = 'Period') and exists (SELECT * FROM information_schema.COLUMNS WHERE TABLE_NAME = 'myview' AND COLUMN_NAME = 'Country'))
begin
select `Period`, `Country` from myview
end
If the IF condition is true, then you will execute anything inside the BEGIN and END.
I came across the same situation where I had some product tables created by sheets uploaded by users. Sometimes, the sheets did not have column named "obsolete", so I had to import all products from the sheet but not the obsolete ones.
I am not modifying my query based on the original question that was asked, but here is my solution:
SELECT
t2.model,
(
SELECT
COUNT(*) AS _count
FROM db.table t1
WHERE
`obsolete`=1
AND t1.model=t2.model
) AS `obsolete`
FROM (
SELECT
0 AS `obsolete`,
t3.model
FROM db.table t3
) t2
There are 2 most important parts in this query:
We are selecting 0 AS obsolete as dummy to fool MySql which will be used even if column does not exist when selecting COUNT(*).
We have named tables as t1 & t2 to match the column model as t1.model=t2.model.
Related
I have a lot of dynamically created nearly similar looking tables according to the scheme "prefix + number", eg "t1", "t2", "t343" etc. All those tables have a cross-table unique row named identifier that I like to select within one query:
SELECT
`identifier`
FROM
(
SELECT
`TABLE_NAME`
FROM
information_schema.TABLES
WHERE
`TABLE_NAME` LIKE 't%'
);
But this returns: ERROR 1248 (42000): Every derived table must have its own alias
EDIT: according to the comments I modified my query like this:
SELECT
A.identifier
FROM
(
SELECT
`TABLE_NAME` AS identifier
FROM
information_schema.TABLES
WHERE
`TABLE_NAME` LIKE 't%'
) A;
But this selects only the table names from the subquery but not the column identifier from these tables.
When you create the table dynamically, and you want to query all of them, you can create an SQL statement dynamically like:
select
group_concat(
concat(
'SELECT ',
'''',TABLE_SCHEMA,'.',TABLE_NAME,''',',
TABLE_SCHEMA,'.',TABLE_NAME,'.', COLUMN_NAME,
' FROM ',
TABLE_SCHEMA,'.',TABLE_NAME)
separator ' union all ')
from information_schema.`COLUMNS` c
where table_schema='test' -- the schema name where your tables are
and table_name regexp '^t[0-9]+$' -- table name starts with t and ends with number
and COLUMN_NAME = 'i' -- i choose `i` as the column to be selected
;
This will produce a SQL statement like:
select
'test.t1',
test.t1.i
from
test.t1
union all
select
'test.t2',
test.t2.i
from
test.t2
union all
select
'test.t3',
test.t3.i
from
test.t3
When putting all of this in a stored procedure, you can use PREPARE and EXECUTE to execute this created statement.
Above is just an example of an SQL statement, you should change it to your needs.
I need to copy/ insert all values with a certain where clause from table A to table B (basically from Main tables to respective history tables).
I don't want to specify the column names as I want to create a generic approach which will be able to use for all the tables that will need the ingestion.
Unfortunately, the attributes in table A are not always in the same order as it is in tableB, so I can't use select * into #temp from TableA and then insert into tableB from #temp. Plus TableB has generic 3 sys columns which we are generated for audit purposes.
My idea was to use the Info schema to get the column names. Then somehow use the result to get all the values from the asking table and add on top the generic sys columns. Is it possible to do?
I got the column names by using Info schema.
Select
COLUMN_NAME
FROM INFORMATION_SCHEMA.columns
where TABLE_NAME = 'TableA'
The SYS columns are:
sys_date=Getdate ()
,sys_flag='1'
,sys_name=SYSTEM_USER
Use Dynamic Query SQL Server
Please change table Name accordingly.
Declare #Table_Name varchar(50)
SET #Table_Name ='LoginMst'
Declare #Query varchar(8000)
Declare #ColumnNames varchar (8000)
set #ColumnNames = ''
select #ColumnNames =
case when #ColumnNames = ''
then column_name
else #ColumnNames + coalesce(',' + column_name, '')
end
from information_schema.columns where Table_Name=#Table_Name
SET #Query='insert into '+#Table_Name+'_Log ('+#ColumnNames+',sys_date,sys_flag,sys_name'+')
select '+#ColumnNames+',Getdate(),''1'',SYSTEM_USER from '+ 'LoginMst'
--print #Query
Exec(#Query)
You will require iterating all the tables you wish to take backup of. You will require adding the where clause too.
I have the following query that I want to use to check whether if a column exists and then insert it if it doesn't.
$new_field ="IF NOT EXISTS
(SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_SCHEMA = 'dashboard'
AND TABLE_NAME = '".$this->table_name."'
AND COLUMN_NAME = 'timestamp')
BEGIN
ALTER TABLE `".$this->table_name."`
ADD mytimestamp DATETIME NOT NULL AFTER day_chan3";
I am not sure where my mistake is as I am not that good at sql queries and I would really aprpeciate the help. I know this looks very n00b and i am one.
I made the changes mentioned in the comment and I echoed the output of my query,
IF NOT EXISTS
(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'dashboard'
AND TABLE_NAME = 'admin_tmp' AND COLUMN_NAME = 'timestamp')
BEGIN ALTER TABLE `admin_tmp` ADD mytimestamp DATETIME NOT NULL AFTER day_chan3
Your if statement is mixing up backticks with single quotes. Use backticks only when necessary and only for identifiers (column names and table names). Use single quotes only for string and date constant values. So, try this:
(SELECT *
FROM information_schema.COLUMNS
WHERE
TABLE_SCHEMA = 'dashboard'
-----------------------------^ --------^
AND TABLE_NAME = '".$this->table_name."'
---------------------------^ --------------------^
AND COLUMN_NAME = 'timestamp')
----------------------------^ --------^
I want to get rows of a table such that no column value is null. No hardcoding of column values. I have hundreds of column names so.
Output should be only row 2 since all that row has the values for all the columns. I do not want to specify all the column names for is not null. It should take it programmatically. Even if i add a new column it should work without changing the query. That is my vision.
I found something, but that means using CURSOR
DECLARE #ColumnName VARCHAR(200)
DECLARE #ColumnCount INT
DECLARE #sql VARCHAR(400)
CREATE TABLE #tempTable (Id INT)
DECLARE GetNonNullRows CURSOR
FOR
SELECT c.NAME, (SELECT COUNT(*) FROM sys.columns col WHERE col.object_id = c.OBJECT_ID) FROM sys.tables AS t
JOIN sys.columns AS c ON t.object_id = c.object_id
WHERE t.name = 'SomeTable' AND t.type = 'U'
OPEN GetNonNullRows
FETCH NEXT FROM GetNonNullRows INTO #ColumnName, #ColumnCount
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = 'SELECT st.UniqueId FROM SomeTable AS st WHERE ' + CONVERT(varchar, #ColumnName) + ' IS NOT NULL'
INSERT INTO #tempTable
EXEC (#sql)
FETCH NEXT FROM GetNonNullRows INTO #ColumnName, #ColumnCount
END
CLOSE GetNonNullRows
DEALLOCATE GetNonNullRows
SELECT * FROM SomeTable AS st1
WHERE st1.UniqueId IN (SELECT Id FROM #tempTable AS tt
GROUP BY Id
HAVING COUNT(Id) = #ColumnCount)
DROP TABLE #tempTable
Let me to explain this a little.
First i create cursor which iterate through all the columns of one table. For each column, I've create sql script to search in table for not null values for selected column. For those rows that satisfies criteria, I take its unique ID and put in temp table, and this job I am using for all columns.
At the end only ID's which count is like columns count are your result set, because only rows that have identical number of appearances like number of columns in table may be rows with all non null values in all columns.
Try this ::
SELECT * FROM mytable WHERE column IS NOT NULL
try this
SELECT *
FROM your_table_name
where coalesce(column_1, column_2, column_3, ...., column_n) is not null
SQL alone cannot express such a concept.
You have to dinamically build the SQL query according to the table definition using some procedural language.
In Oracle you can use the dictionay view USER_TAB_COLUMNS to build the column list.
try using IS NOT NULL
SELECT * FROM table WHERE field_name IS NOT NULL
For more information, check out the mysql manual on working with null values.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I merge two MySql tables?
I want to merge multiple tables that have the same structure and make one large table. The tables have similar names, so I want to use the LIKE statement. Can anyone tell me how I can do this?
The tables are very simple, each having an ID column and a few other columns, but there are a large amount of tables, all of which have names like 'TX-xxx', where 'TX' means Texas, and 'xxx' are the counties in Texas; you know there are more than 200 counties in Texas. (In fact, I have to do this for all the states.) So I want to use the statement "LIKE 'TX-___'".
Thanks!
You would have to give more information so we know exactly what you want but you could create a view
CREATE VIEW myViewName AS
select *
from table1
union all
select * from
table2
This way it would show the information from all your tables (and can be limited so in the selects to not show everything) and when table1, table2, etc are changed the view will reflect this. You can change it at anytime and fetch from it as you would a table:
select * from myViewName
Now for grabbing from specific tables I am not sure how you can do this in mysql though I have done it in tsql. This previous question would help you so you might have something like:
-- Create temporary table of varchar(200) to store the name of the tables. Depending on how you want to go through the array maybe an id number (int).
insert into tempTableName (name)
SELECT table_name FROM information_schema.tables WHERE table_schema = 'database_name' and table_name like 'TX_%';
declare #sqlQuery varchar(max)
--Then you will want to loop through the array and build up an sql statement
-- For each loop through:
if len(#sqlQuery) = 0 begin -- first time through
set #sqlQuery = 'select col1, col2, col3 from ' + currentTableName
end else begin -- second+ time through
set #sqlQuery = 'union all select col1, col2, col3 from ' + currentTableName
end
-- after the loop add the create view. Could double check it worked by checking length = 0 again
set #sqlQuery = 'CREATE VIEW myViewName AS ' + #sqlQuery
Once the query string is built up you will execute it with
PREPARE stmt FROM #sqlQuery;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
If I understand your question correctly UNION is what you need. Something like
SELECT field1, field2
FROM (
SELECT field1, field2 from table1
UNION
SELECT field1, field2 from table2
) all_tables
WHERE all_tables.field1 like "%whatever%
Assuming they have the same columns or similar:
insert into #table
Select * from (Select * from tbl1
Union
select * from tbl2
Union
select * from tbl3)
If they don't have the same number/type of columns then you should provide us with that information.