Knows Not Much
Knows Not Much

Reputation: 31546

Why doesn't my mysql code work

I wrote this code and when I execute it it says I have a problem with mysql syntax near the update statement

set @s1 = (select if ((select count(*) from information_schema.columns where table_name='foo' and column_name='bar_id') > 0,
                      'select 1',
                      'alter table foo add column bar_id bigint; update foo set bar_id = baz_id;'));
prepare stmt from @s1;
execute stmt;
deallocate prepare stmt;

If I change my code to

set @s1 = (select if ((select count(*) from information_schema.columns where table_name='foo' and column_name='bar_id') > 0,
                      'select 1',
                      'alter table foo add column bar_id bigint;'));
prepare stmt from @s1;
execute stmt;
deallocate prepare stmt;
update foo set bar_id = baz_id;

then it works. but I want the update statement inside the if condition.

I cannot make this into a SP.

Error:

ERROR 1064 (42000): 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 'update foo set bar_id = baz_id' at line 1

Upvotes: 1

Views: 222

Answers (2)

bishop
bishop

Reputation: 39394

In your first code block, you attempt to prepare a string that contains two SQL statements. Unfortunately, MySQL prepare / execute cannot have multiple statements.

If you can't use SP, I think I'd suggest doing this like so:

set @s1 = (select if ((select count(*) from information_schema.columns where table_name='foo' and column_name='bar_id') > 0,
                      'select 1',
                      concat('alter table foo add column bar_id bigint default ', baz_id)));

prepare stmt from @s1;
execute stmt;
deallocate prepare stmt;

alter table foo alter column bar_id drop default;

But, honestly, I'd suggest you minimize DDL changes as those can have unpredictable run-time behavior. In this case, that means adding the foo.bar_id out-of-band and just perform an update as needed.

Upvotes: 2

slaakso
slaakso

Reputation: 9070

The problem is that MySQL's prepared statements do not support multi-statements.

If you want to script the database structure updates, easiest way is to use a procedure without dynamic SQL (you might want to check the table_schema as well when you are doing the changes).

create procedure sp_fix_structure()
begin

declare v_cnt int;

select count(*) into v_cnt
from information_schema.columns
where table_schema=database() and table_name='foo' and column_name='bar_id';

if (v_cnt=0) then
  alter table foo add column bar_id bigint;
  update foo set bar_id = baz_id;
end if;

end

Upvotes: 0

Related Questions