How do I check whether column exists in the table? - mysql

I need to check whether mytable table is containing mycolumn column? Here is my query:
SELECT CASE WHEN EXISTS (SHOW COLUMNS FROM mytable LIKE mycolumn) THEN 1 ELSE 0 END;
But it doesn't work and throws this error-message:
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'SHOW COLUMNS FROM mytable LIKE mycolumn) THEN 1 ELSE 0 END at line 1
What's wrong and how can I fix it?

You can use the following as an if
IF EXISTS(
select * from
INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME ='SOMETABLE' AND
COLUMN_NAME = 'SOMECOLUMN')
)
BEGIN
-- do stuff
END
GO
Alternatively as a case
SELECT CASE WHEN EXISTS(
select * from
INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME ='TABLE_NAME' AND
COLUMN_NAME = 'COLUMN_NAME')
Then 1 Else 0 End;

Try this instead
SELECT CASE WHEN EXISTS (
SELECT * FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'db_name'
AND TABLE_NAME = 'table_name'
AND COLUMN_NAME = 'column_name')
then 1
else 0
end;

If you need to pass the Table and Column name dynamically , please use this.
DECLARE #Table Varchar(100)
DECLARE #Column Varchar(100)
DECLARE #Query nvarchar(max)
SET #Table ='MyTable'
SET #Column ='MyColumn'
SET #Query ='select * from
INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME ='''+#Table+''' AND
COLUMN_NAME IN ('''+#Column+''')'
EXEC (#Query)

Related

IF NOT EXISTS SyntaxError in MySQL

I'm trying to write a kind of update SQL to add new columns if they don't already exist.
I've already tried a few things, but nothing works.
If I try an IF NOT EXISTS I always get a syntax error that I can't understand.
IF NOT EXISTS(
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'nutzer'AND table_schema = 'restdb' AND column_name = 'api_nutzer')
THEN
ALTER TABLE `nutzer` ADD `api_nutzer` TINYINT;
END IF;
[SQL] IF NOT EXISTS( SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'nutzer'
AND table_schema = 'restdb'
AND column_name = 'api_nutzer') THEN
ALTER TABLE `nutzer` ADD `api_nutzer` TINYINT;
[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF NOT EXISTS( SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
' at line 1
If I execute the SELECT directly, I get a result
Does anyone have an idea or know where my mistake is?
I use MySQL Server Version 8.0.22
I have understood that the Exists clause can be used in the WHERE section
SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);
try to reconstruct your query for captured if the row exists
for example
<i>if( /*begin extra condition*/ Select 1 where exists
(SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'nutzer'
AND table_schema = 'restdb'
AND column_name = 'api_nutzer') = 1 /*end extra condition*/) then
ALTER TABLE `nutzer` ADD `api_nutzer` TINYINT;</i>
Thanks for your help i get an solutuion for my Problem.
DROP PROCEDURE IF EXISTS addCol;
CREATE PROCEDURE addCol(
IN tabelle VarChar(255),
IN spalte VarChar(255),
IN type VarChar(255)
)
BEGIN
IF NOT EXISTS (
SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = tabelle
AND TABLE_SCHEMA = 'restdb'
AND COLUMN_NAME = spalte
)
THEN
SET #ddl = CONCAT(' alter table ', tabelle ,' ADD ', spalte, ' ', type);
PREPARE STMT FROM #ddl;
EXECUTE STMT;
END IF;
END

How to get a specific column by its ordinal position in table using SQL? [duplicate]

Is there any SQL lingo to return JUST the first two columns of a table WITHOUT knowing the field names?
Something like
SELECT Column(1), Column(2) FROM Table_Name
Or do I have to go the long way around and find out the column names first? How would I do that?
You have to get the column names first. Most platforms support this:
select column_name,ordinal_position
from information_schema.columns
where table_schema = ...
and table_name = ...
and ordinal_position <= 2
There it´s
declare #select varchar(max)
set #select = 'select '
select #select=#select+COLUMN_NAME+','
from information_schema.columns
where table_name = 'TABLE' and ordinal_position <= 2
set #select=LEFT(#select,LEN(#select)-1)+' from TABLE'
exec(#select)
A dynamic query using for xml path will also do the job:
declare #sql varchar(max)
set #sql = (SELECT top 2 COLUMN_NAME + ',' from information_schema.columns where table_name = 'YOUR_TABLE_NAME_HERE' order by ordinal_position for xml path(''))
set #sql = (SELECT replace(#sql +' ',', ',''))
exec('SELECT ' + #sql + ' from YOUR_TABLE_NAME_HERE')
I wrote a stored procedure a while back to do this exact job. Even though in relational theory there is no technical column order SSMS is not completely relational. The system stores the order in which the columns were inserted and assigns an ID to them. This order is followed using the typical SELECT * statement which is why your SELECT statements appear to return the same order each time. In practice its never a good idea to SELECT * with anything as it doesn't lock the result order in terms of columns or rows. That said I think people get so stuck on 'you shouldn't do this' that they don't write scripts that actually can do it. Fact is there is predictable system behavior so why not use it if the task isn't super important.
This SPROC of course has caveats and is written in T-SQL but if your looking to just return all of the values with the same behavior of SELECT * then this should do the job pretty easy for you. Put in your table name, the amount of columns, and hit F5. It returns them in order from left to right the same as you'd be expecting. I limited it to only 5 columns but you can edit the logic if you need any more. Takes both temp and permanent tables.
EXEC OnlySomeColumns 'MyTable', 3
/*------------------------------------------------------------------------------------------------------------------
Document Title: The Unknown SELECT SPROC.sql
Created By: CR
Date: 4.28.2013
Purpose: Returns all results from temp or permanent table when not knowing the column names
SPROC Input Example: EXEC OnlySomeColumns 'MyTable', 3
--------------------------------------------------------------------------------------------------------------------*/
IF OBJECT_ID ('OnlySomeColumns', 'P') IS NOT NULL
DROP PROCEDURE OnlySomeColumns;
GO
CREATE PROCEDURE OnlySomeColumns
#TableName VARCHAR (1000),
#TotalColumns INT
AS
DECLARE #Column1 VARCHAR (1000),
#Column2 VARCHAR (1000),
#Column3 VARCHAR (1000),
#Column4 VARCHAR (1000),
#Column5 VARCHAR (1000),
#SQL VARCHAR (1000),
#TempTable VARCHAR (1000),
#PermanentTable VARCHAR (1000),
#ColumnNamesAll VARCHAR (1000)
--First determine if this is a temp table or permanent table
IF #TableName LIKE '%#%' BEGIN SET #TempTable = #TableName END --If a temporary table
IF #TableName NOT LIKE '%#%' BEGIN SET #PermanentTable = #TableName END --If a permanent column name
SET NOCOUNT ON
--Start with a few simple error checks
IF ( #TempTable = 'NULL' AND #PermanentTable = 'NULL' )
BEGIN
RAISERROR ( 'ERROR: Please select a TempTable or Permanent Table.',16,1 )
END
IF ( #TempTable <> 'NULL' AND #PermanentTable <> 'NULL' )
BEGIN
RAISERROR ( 'ERROR: Only one table can be selected at a time. Please adjust your table selection.',16,1 )
END
IF ( #TotalColumns IS NULL )
BEGIN
RAISERROR ( 'ERROR: Please select a value for #TotalColumns.',16,1 )
END
--Temp table to gather the names of the columns
IF Object_id('tempdb..#TempName') IS NOT NULL DROP TABLE #TempName
CREATE TABLE #TempName ( ID INT, Name VARCHAR (1000) )
--Select the column order from a temp table
IF #TempTable <> 'NULL'
BEGIN
--Verify the temp table exists
IF NOT EXISTS ( SELECT 1
FROM tempdb.sys.columns
WHERE object_id = object_id ('tempdb..' + #TempTable +'') )
BEGIN
RAISERROR ( 'ERROR: Your TempTable does not exist - Please select a valid TempTable.',16,1 )
RETURN
END
SET #SQL = 'INSERT INTO #TempName
SELECT column_id AS ID, Name
FROM tempdb.sys.columns
WHERE object_id = object_id (''tempdb..' + #TempTable +''')
ORDER BY column_id'
EXEC (#SQL)
END
--From a permanent table
IF #PermanentTable <> 'NULL'
BEGIN
--Verify the temp table exists
IF NOT EXISTS ( SELECT 1
FROM syscolumns
WHERE id = ( SELECT id
FROM sysobjects
WHERE Name = '' + #PermanentTable + '' ) )
BEGIN
RAISERROR ( 'ERROR: Your Table does not exist - Please select a valid Table.',16,1 )
RETURN
END
SET #SQL = 'INSERT INTO #TempName
SELECT colorder AS ID, Name
FROM syscolumns
WHERE id = ( SELECT id
FROM sysobjects
WHERE Name = ''' + #PermanentTable + ''' )
ORDER BY colorder'
EXEC (#SQL)
END
--Set the names of the columns
IF #TotalColumns >= 1 BEGIN SET #Column1 = (SELECT Name FROM #TempName WHERE ID = 1) END
IF #TotalColumns >= 2 BEGIN SET #Column2 = (SELECT Name FROM #TempName WHERE ID = 2) END
IF #TotalColumns >= 3 BEGIN SET #Column3 = (SELECT Name FROM #TempName WHERE ID = 3) END
IF #TotalColumns >= 4 BEGIN SET #Column4 = (SELECT Name FROM #TempName WHERE ID = 4) END
IF #TotalColumns >= 5 BEGIN SET #Column5 = (SELECT Name FROM #TempName WHERE ID = 5) END
--Create a select list of only the column names you want
IF Object_id('tempdb..#FinalNames') IS NOT NULL DROP TABLE #FinalNames
CREATE TABLE #FinalNames ( ID INT, Name VARCHAR (1000) )
INSERT #FinalNames
SELECT '1' AS ID, #Column1 AS Name UNION ALL
SELECT '2' AS ID, #Column2 AS Name UNION ALL
SELECT '3' AS ID, #Column3 AS Name UNION ALL
SELECT '4' AS ID, #Column4 AS Name UNION ALL
SELECT '5' AS ID, #Column5 AS Name
--Comma Delimite the names to insert into a select statement. Bracket the names in case there are spaces
SELECT #ColumnNamesAll = COALESCE(#ColumnNamesAll + '], [' ,'[') + Name
FROM #FinalNames
WHERE Name IS NOT NULL
ORDER BY ID
--Add an extra bracket at the end to complete the string
SELECT #ColumnNamesAll = #ColumnNamesAll + ']'
--Tell the user if they selected to many columns
IF ( #TotalColumns > 5 AND EXISTS (SELECT 1 FROM #FinalNames WHERE Name IS NOT NULL) )
BEGIN
SELECT 'This script has been designed for up to 5 columns' AS ERROR
UNION ALL
SELECT 'Only the first 5 columns have been selected' AS ERROR
END
IF Object_id('tempdb..#FinalNames') IS NOT NULL DROP TABLE ##OutputTable
--Select results using only the Columns you wanted
IF #TempTable <> 'NULL'
BEGIN
SET #SQL = 'SELECT ' + #ColumnNamesAll + '
INTO ##OutputTable
FROM ' + #TempTable + '
ORDER BY 1'
EXEC (#SQL)
END
IF #PermanentTable <> 'NULL'
BEGIN
SET #SQL = 'SELECT ' + #ColumnNamesAll + '
INTO ##OutputTable
FROM ' + #PermanentTable + '
ORDER BY 1'
EXEC (#SQL)
END
SELECT *
FROM ##OutputTable
SET NOCOUNT OFF
SQL doesn't understand the order of columns. You need to know the column names to get them.
You can look into querying the information_schema to get the column names. For example:
SELECT column_name
FROM INFORMATION_SCHEMA.COLUMNS
WHERE table_name = 'tbl_name'
ORDER BY ordinal_position
LIMIT 2;
You can query the sysobject of the table to find out the first two column then dynamically generate the SQL statement you need.
If you want a permant object that you can query over and over again make a view for each table that only returns the first 2 columns. You can name the columns Column1 and Column2 or use the existing names.
If you want to return the first two columns from any table without any preprocessing steps create a stored procedure that queries the system information and executes a dynamic query that return the first two columns from the table.
Or do I have to go the long way around and find out the column names first? How would I do that?
It's pretty easy to do manually.
Just run this first
select * from tbl where 1=0
This statement works on all major DBMS without needing any system catalogs.
That gives you all the column names, then all you need to do is type the first two
select colname1, colnum2 from tbl

How to write MySQL to get count of distinct values in a table?

Suppose database.tbl contains two fields: fruit and price.
Row 1: fruit='apple', price=0.60.
Row 2: fruit='pear', price=0.60.
Row 3: fruit='peach', price=0.50.
I want to run a query which returns the count of distinct values for each field, i.e. it should return
fruit 3
price 2
because there are 3 fruits, but only 2 distinct prices.
I've tried
SELECT C.COLUMN_NAME, COUNT(DISTINCT C.COLUMN_NAME) FROM tbl JOIN (SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='database' AND TABLE_NAME='tbl') AS C GROUP BY C.COLUMN_NAME;
but this returns:
fruit 1
price 1
The only way I know to do it is to take the column names from the INFORMATION_SCHEMA query and put them in a temp table. Then iterate over the column names in the temp table and execute dynamic sql to query the distinct values in those columns. Here is an example in T-SQL, so you'll have to make some changes.
CREATE TABLE #values
(
COLUMN_NAME VARCHAR(100),
DISTINCT_COUNT INT
)
DECLARE #column AS VARCHAR(100) = ''
SELECT COLUMN_NAME INTO #columns FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='dbo' AND TABLE_NAME='tbl'
SELECT TOP 1#column = COLUMN_NAME
FROM #columns
WHERE COLUMN_NAME > #column
ORDER BY COLUMN_NAME ASC
WHILE (##ROWCOUNT > 0)
BEGIN
DECLARE #sql AS NVARCHAR(1000) = N'INSERT INTO #values (COLUMN_NAME, DISTINCT_COUNT) SELECT ''' + #column + ''', COUNT(DISTINCT ' + #column + N') FROM [db].[dbo].[tbl]'
EXECUTE sp_executesql #sql
SELECT TOP 1 #column = COLUMN_NAME
FROM #columns
WHERE COLUMN_NAME > #column
ORDER BY COLUMN_NAME ASC
END
SELECT * FROM #values
DROP TABLE #columns
DROP TABLE #values
This is pretty rough and just an example of how it can be done. If this were production code, I'd make sure the variable types are all consistent and make sure the column names are safe. This will help: How To have Dynamic SQL in MySQL Stored Procedure

Checking column exists with If else condition in sql

I'm trying to check weather thw column exists or not
IF (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tb_consumer' AND COLUMN_NAME='businness_id' > 0 ) THEN
PRINT 'test'
Whats wrong with above sql? getting error as
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'IF (Select COUNT(*) From INFORMATION_SCHEMA.COLUMNS Where TABLE_NAME = 'tb_consu' at line 1
New to SQL. Thanks for any help,
Version of MySql is 5.X
You can fix the query by moving the closing paren:
IF (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tb_consumer' AND COLUMN_NAME = 'businness_id'
) > 0 THEN
PRINT 'test'
A better way to write the condition is using exists:
IF EXISTS (SELECT 1
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tb_consumer' AND COLUMN_NAME = 'businness_id'
) THEN
If you try to use this as part of a stored procedure, you might take a look at the if statement in the mysql documentation
if you do this as part of a normal query, you can write it like
SELECT IF (COUNT(*) > 0, 'TEST, 'TEST FAILED') FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'tb_consumer' AND COLUMN_NAME='businness_id'
i would suggest using CASE statement in MYSQL
SELECT CASE
WHEN COLUMN_NAME = 'businness_id' then 'TEST'
END
from FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tb_consumer'
Case statements are faster on smaller databases
SQL command is not a Boolean function.
Therefore you need to check the value.
Like this:
IF (SELECT COUNT(*)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'tb_consumer' AND COLUMN_NAME='businness_id') >= 0
THEN PRINT 'test'

Output variable from dynamic SQL

I have an issue wen I try to output a value from a dynamic T-SQL Query inside of a stored procedure.
I try to execute the following and simply output a 1 if something was found:
SET NOCOUNT ON
DECLARE #returnValue int
DECLARE #Statement nvarchar(400)
set #Statement = 'SELECT #result=''1'' FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''sourceTable''
AND COLUMN_NAME = #columnIN
AND TABLE_SCHEMA = ''dbo'''
exec sp_executesql #Statement,
N'#columnIN nvarchar(60),#result INT OUTPUT',
#columnIN = #column, #result=#returnValue OUTPUT
select #returnValue
This currently yields NULL. Does anyone have any idea what I'm missing?
Additional Information:
The column that I try to lookup is for example column1 . If I run the SQL query with ...AND CLOUMN_NAME = 'column1' ... I get a 1 back.
If I print the #column variable in the SP I get 'column1'.
#column is declared as an input variable with nvarchar(60) in the SP: PROCEDURE [dbo].[usp_checkColumn] (#column nvarchar(60), #result INT OUTPUT)
As per request the complete SP here:
Create PROCEDURE [dbo].[usp_checkColumn] (#column nvarchar(60), #result INT OUTPUT)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON
DECLARE #returnValue int
DECLARE #Statement nvarchar(400)
set #Statement = 'SELECT #result=''1'' FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = ''t_table''
AND COLUMN_NAME = #columnIN
AND TABLE_SCHEMA = ''dbo'''
exec sp_executesql #Statement, N'#columnIN nvarchar(60),#result INT OUTPUT', #columnIN = #column, #result=#returnValue OUTPUT
select #returnValue
return #returnValue
END
And here's how I call the SP:
DECLARE fcursor CURSOR
FOR
select FieldName
from t_fieldDefinition
OPEN fcursor
Fetch next from fcursor into #field;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #tmpField = '''' + #field + ''''
SET #field ='[' + #field + ']'
set #available = 0
exec usp_checkColumn #tmpField,#available OUTPUT
If I print the [#column] variable in the usp_checkColumn I do get the correct column inside of the ''. If I copy & paste the print of this variable and insert it into the query I get a 1 back, if I run the SP I get NULL(converted to 0 as NULL is not valid for the INT variable) back.
Here's the content of the t_fieldDefinition table:
FieldName ID
Source 5
column1 6
column2 7
Client 8
asd BSX 9
bsd 10
esd 11
esx 12
And here's the definition of the t_table table:
ID bigint Unchecked
Source varchar(250) Checked
column1 varchar(250) Checked
column2 nvarchar(100) Checked
Client varchar(10) Checked
asd varchar(250) Checked
[asd BSX] varchar(250) Checked
so that means that it should return 1 for all that are inside of the table definition and 0 for all others. Is it possible that the fields with a white space can be the issue? Although they work as well when you do it manually. It's not that I really have an option to change it but at least I would now the cause of the issue then.
I'm going to venture an answer on this.
I do not recommend using a cursor to go through each column just to test if the column exists in another table. If you insist on using a cursor, you could use a subquery to limit the results that you're cycling through to only the columns that don't exist in the other table, eliminating the need for the stored procedure that checks each individually (which by the way I think makes more sense as a user function):
DECLARE fcursor CURSOR
FOR
SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS
where table_name = 't_table' and not column_name in
(
SELECT COLUMN_Name FROM INFORMATION_SCHEMA.COLUMNS
where table_name = 't_fieldDefinition'
)
If your goal really is to alter the table to add any missing columns, then this can be improved by eliminating the cursor and outputting your results using FOR XML:
declare #sql varchar(max)
set #sql =
(
SELECT cast('ALTER TABLE t_fieldDefinition ADD [' + COLUMN_NAME + '] INT;' as varchar(max)) FROM INFORMATION_SCHEMA.COLUMNS
where table_name = 't_table' and not column_name in
(
SELECT COLUMN_Name FROM INFORMATION_SCHEMA.COLUMNS
where table_name = 't_fieldDefinition'
) FOR XML PATH ('')
)
print #sql
exec (#sql)