0

I have searched everything I could ) Truly. But I can't find the correct way to add new columns only after checking if the column doesn't exist. I am writing a program in C. Here is what I am doing, and I can't find my mistake in syntax. I will be very grateful for your help! I get an error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use

//create buffer to store the query
char buff[1024];
//store query in the buffer                
snprintf(buff, sizeof buff, "IF NOT EXISTS(SELECT * FROM information_schema.COLUMNS WHERE COLUMN_NAME = '%i' AND TABLE_NAME = '%s' AND TABLE_SCHEMA = '%s') THEN ALTER TABLE `%s`.`%s` ADD COLUMN `%i` INT; END IF;", value1, table, database, database, table, value1);

EDIT

I am editing the post to show what I am trying to achieve. Using nested if statement in the main function, I have created the database and the table, and have populated the table with column names; my code is designed in a way that all functions are interrelated: only if connection is established, the program calls "create database" function; only if database is created, the program calls "create table" function; only if the table is created and initially only two columns are added (id and Names), the program calls the function to alter table in order to add other columns.

I do so because I need a for loop to loop those additional column names, which were created previously by my previous C program. So the table should look like this:

id   name   1988   1977   1966   1955
1    name1  value  value  value  value
2    name2  value  value  value  value
3    name3  value  value  value  value

Each time the program is called, each function checks if database exists, then it is not created from scratch, if table exists, it is not created, and now I am stumbled on how to check of columns exist, because if they do, I get an error and the program can't move on.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
Vitale
  • 129
  • 6
  • Don't use `sprintf()` use prepared statements and parameters through `MYSQL_BIND` structure. Also, I am worried as to why will you add columns if they don't exist, that looks like a design error. – Iharob Al Asimi Feb 05 '17 at 13:26
  • IF can only be used inside a procedure, trigger etc. – Ôrel Feb 05 '17 at 13:28
  • 1
    http://stackoverflow.com/questions/8219714/check-if-column-exists-before-alter-table-mysql can help – Ôrel Feb 05 '17 at 13:29
  • The correct way to add a column is `ATER TABLE table ADD COLUMN IF NOT EXISTS name TYPE;`. – Iharob Al Asimi Feb 05 '17 at 13:30
  • @Iharob Al Asimi I have tried this syntax, but it didn't work; got the syntax error as well. Then I searched everywhere, and have found out that this syntax is not yet implemented in mysql. – Vitale Feb 05 '17 at 14:49
  • @Vitale I just tried it and it works perfectly, although I am using archlinux which brings MariaDB instead of MySQL but I am not aware of MariaDB implementing this feature while MySQL not. – Iharob Al Asimi Feb 05 '17 at 14:50
  • @Vitale you did improve your question now, my recommendation is that you read about SQL databases and relational databases concepts, in particular what a schema is and how to properly design one for your particular problem. I have added an example below in my answer so that you get started, bottom line **DO NOT USE A SQL DATABASE WITH A DYNAMIC SCHEMA**, it just doesn't make sense. – Iharob Al Asimi Feb 05 '17 at 15:19
  • One reason why it's so hard to do it the way you want is because it's not meant to. – Iharob Al Asimi Feb 05 '17 at 15:23

1 Answers1

0

To add a column you can do it like this

snprintf(
    buff, 
    sizeof buff, 
    "ALTER TABLE `%s`.`%s` ADD COLUMN IF NOT EXISTS `%s` `%s`", 
    database,
    table, 
    column_name, 
    column_type
);

Note that in your format string there is a %i that doesn't look right.

After giving you the answer, because this is what you asked for, I want to say that adding a column in code like that looks like a bad sign. SQL databases are pretty static in their structure, you should never need to add or remove columns from it. If you have to, then there is a problem either in the database design or the way you are handling it.

According to the comments below you need something like this

CREATE TABLE `names` (
    `name` VARCHAR(128) PRIMARY KEY
) ENGINE = InnoDB;

CREATE TABLE `entries` (
    `name` VARCHAR(128) NOT NULL,
    `year` INTEGER NOT NULL,
    -- Or the required type (FLOAT perhaps?)
    `value` INTEGER NOT NULL,
    -- All names MUST come from the `names` table
    CONSTRAINT `name_fk` FOREIGN KEY (`name`) REFERENCES `names` (`name`),
    -- Allow only one entry per `name`/`year`
    CONSTRAINT `entry_pk` PRIMARY KEY (`name`, `year`)
) ENGINE = InnoDB;

And then you can insert each name in the names table, and one entry per year in the entries table, you can have the combinations you want and you can query all years for a given name

SELECT * FROM `entries` WHERE `name` = ?

Creating a database schema dynamically is wrong, it's just against the whole idea of a schema, a database has a schema so you can write queries an rely on them working, the language is called Structured Query Language for a reason.

Iharob Al Asimi
  • 52,653
  • 6
  • 59
  • 97
  • Thank you very much. I have tried it, and got the syntax error. I will try it again of course. I can't use anything but %i in that one instance, because the value I am passing is an integer, and all columns have numbers as names. For example, they will be named: 789 or 1298 – Vitale Feb 05 '17 at 14:52
  • @Vitale that seems very unreliable. Can you tell me why are you trying to do this? This is a very bad idea. It appears that you have a [xy problem](http://www.xyproblem.info/) here. – Iharob Al Asimi Feb 05 '17 at 14:58
  • I have tried it again; used the version you have - the one without closing `;` before double quotes in ALTER TABLE statement; and also the version with those `;`. Same error: `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 `1988` INTEGER' at line 1` – Vitale Feb 05 '17 at 15:00
  • Oh, I will be truly grateful if you explain what is wrong with this choice. My goal is to populate the table with values I have computed using C. I have: (1) row names that go vertically from top down (name1, below it goes name2, below name3, etc, making a column of names); (2) then, as each name represents a row, I populate each row with values, and each value corresponds to a certain year; and this is why my columns have integer names - they are years. I will update my original post and will try to show how the table should look like. – Vitale Feb 05 '17 at 15:04
  • You need to create a database that allows you to do that instead, a year should not be a column but instead a value of a column in a given row. This really doesn't make sense, at least it doesn't make sense to use a SQL database for this. If you want, tell me more about it to see if a can help you, my email is iharob@gmail.com – Iharob Al Asimi Feb 05 '17 at 15:07
  • Thank you very much. As I am learning C, I got used to flexibility and to the ability to use dynamic approach. – Vitale Feb 05 '17 at 16:21
  • @Vitale Note that this is actually more flexible, but SQL databases are like that. – Iharob Al Asimi Feb 05 '17 at 16:22