1

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

Martin
  • 22,212
  • 11
  • 70
  • 132
Knows Not Much
  • 30,395
  • 60
  • 197
  • 373

2 Answers2

2

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.

bishop
  • 37,830
  • 11
  • 104
  • 139
0

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
slaakso
  • 8,331
  • 2
  • 16
  • 27