I'm fairly new to mySQL. Let's say I'm adding columns to my table like so:
ALTER TABLE table ADD client_input_2.0_1 LONGTEXT;
And I would like to add a number of similar sequential columns, i.e.
ALTER TABLE table ADD client_input_2.0_2 LONGTEXT;
ALTER TABLE table ADD client_input_2.0_3 LONGTEXT;
ALTER TABLE table ADD client_input_2.0_4 LONGTEXT;
etc. all the way up to a large enough number that this will take quite some time if I do this manually. In my case, 2.0 represents a section/part, and the last number represents a question number, which could be anywhere from 1-50 or so depending on the section, so manually creating this table would take a lot of time.
Is there a way for me to do this in a script using some sort of loop, incrementing the col# each time?
Much appreciated,
Edited code
try using a stored procedure
DELIMITER $$
DROP PROCEDURE IF EXISTS RepeatLoopProc$$
CREATE PROCEDURE RepeatLoopProc()
BEGIN
DECLARE x INT;
DECLARE str VARCHAR(255);
Declare #sql nvarchar(4000);
SET x = 0;
REPEAT
SET str = '';
SET str = CONCAT(str,'client_input_2.0_',x);
SET x = x + 1;
set #sql='ALTER TABLE table_name ADD '+ str +' column-definition';
exec sp_executesql #sql;
UNTIL x > 50
END REPEAT;
END$$
DELIMITER ;
Hope this will help you.
I think maybe you should use another approach:
ALTER TABLE table ADD col LONGTEXT, ADD col_index INT.
and use col_index to track the col's purpose
Related
I am a beginner to MYSQL and currently practicing stored procedures. I am trying to create a procedure that should fetch a row of an entire field when given an input parameter. Is there any workaround for this? If yes, then it would be an immense help.
Many Thanks
Welcome to the Forum.
A stored procedure can simple consist of a SELECT statement that returns all the columns in the row you want. e.g.
CREATE PROCEDURE `myproc`(IN `p_id` INT(11))
READS SQL DATA
SELECT id, COL2, COL3, ETC
FROM `mytable`
WHERE id = 'p_id';
If you need to traverse a table, looking at every row that meets some criteria, then you need to DECLARE a "cursor", and use that to fetch the rows you want. Here is a template I use to create new procedures that need to traverse a table - it can be adapted to suit your needs. In this template I nly retrieve two columns from the cursor, but you can retrieve any number. You have to declare a local variable for each column in your SELECT so the FETCH statement has somewhere to put the data it retrieves from the cursor:
CREATE PROCEDURE `traverse_table`()
READS SQL DATA
BEGIN
DECLARE var_id INT(11) UNSIGNED;
DECLARE var_data varchar(16383);
DECLARE done INT DEFAULT FALSE;
DECLARE ecode varchar(1000) ;
DECLARE emsg varchar(1000) ;
DECLARE nextrecord CURSOR FOR # here is the CURSOR DECLARATION
SELECT `myid`,`mydata` # It will return these rows, one
FROM `mytable` # at a time
WHERE `mydata` LIKE "ABC%";
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 ecode = RETURNED_SQLSTATE, emsg = MESSAGE_TEXT;
SELECT var_id,var_data,ecode,emsg;
END;
OPEN nextrecord;
FETCH nextrecord into var_id,var_data; # here is the first Fetch
WHILE (done = FALSE) DO
# >>>>>> do something with var_id,var_data here <<<<<<
SET done = FALSE;
FETCH NEXT FROM records into var_id,var_data; # here is the second and subsequent Fetch
END WHILE;
CLOSE nextrecord;
END
I Have a Database in mysql, i have a principal table that use a column name cedula VARCHAR (50), the column have characters, but i want to change it with a consecutive number. I tried with this:
SET #a:=1;
UPDATE bdpiiad2.tpersona
SET cedula=(CONVERT(#a:=#a+1, CHAR(50)))
But i have 2 problems, first doesn't change, and second I'm not sure if change the other ids in the others tables that have a reference.
try using this
SET #a:=1;
UPDATE bdpiiad2.tpersona
SET cedula=(CAST(#a:=#a+1 as CHAR));
to update all you need to create a procedure like this
DELIMITER $$
USE `bdpiiad2`$$
DROP PROCEDURE IF EXISTS bdpiiad2.`up`$$
CREATE PROCEDURE `up`()
BEGIN
DECLARE max_cnt INT;
DECLARE cnt INT;
SET cnt=1;
UPDATE bdpiiad2.tpersona SET cedula='0';
SELECT COUNT(*) INTO max_cnt FROM bdpiiad2.tpersona;
WHILE cnt<=max_cnt DO
UPDATE bdpiiad2.tpersona
SET cedula=(CAST(cnt AS CHAR))
WHERE cedula='0' LIMIT 1;
SET cnt=cnt+1;
END WHILE;
END$$
DELIMITER ;
and then call it like this
CALL bdpiiad2.up();
I'd like to create a dynamic procedure wich will generate the columns for me automatically but somethings wrong. I have to do this a few times in my program and I don't really want to do it manually.
So thats the code that I used before
DELIMITER $$
DROP PROCEDURE IF EXISTS RepeatLoopProc$$
CREATE PROCEDURE RepeatLoopProc()
BEGIN
DECLARE x INT;
DECLARE str VARCHAR(255);
Declare #sql nvarchar(4000);
SET x = 0;
REPEAT
SET str = '';
SET str = CONCAT(str,'ossz_levon_het_',x);
SET x = x + 1;
set #sql='ALTER TABLE telephelyi_teszt ADD '+ str +'DOUBLE NULL';
execute #sql;
UNTIL x > 50
END REPEAT;
END$$
DELIMITER ;
I've got a syntax error near the Declare #sql nvarchar(4000); line any ideas?
When you use DECLARE to create local variables in a stored procedure, don't use the # prefix. Those are for session variables.
But you shouldn't DECLARE the variable anyway. Prepared statements don't work with local variables, only session variables. You don't have to declare session variables.
Your ALTER TABLE statement has an error. You didn't put a space after the column name and before DOUBLE. In other words, the statement will be like the following, which will cause a syntax error wen you execute it.
ALTER TABLE telephelyi_teszt ADD ossz_levon_het_1DOUBLE NULL
You didn't PREPARE the statement. You can't just EXECUTE a string as a statement. See examples in the manual on prepared statements.
It's probably bad design to create 50 columns in any table with identical content. Consider creating a second table, with one column ossz_levon_het and a reference back to your parent table telephelyi_teszt. This is the recommendation of First Normal Form to avoid repeating groups of columns.
For testing, is it possible to run a loop from MySQL workbench or similar tool? I tried but got an error.
If it is possible, please supply a simple example I can run.
You can't do a for loop in an SQL editor without a stored procedure. I use TOAD for MySQL.
A quick stored procedure should do the job:
DELIMITER $$
DROP PROCEDURE IF EXISTS proc_loop_test$$
CREATE PROCEDURE proc_loop_test()
BEGIN
DECLARE int_val INT DEFAULT 0;
test_loop : LOOP
IF (int_val = 10) THEN
LEAVE test_loop;
END IF;
SET int_val = int_val +1;
SELECT int_val;
END LOOP;
END$$
DELIMITER ;
There's a trick with limited use-cases that is "loop-like".
I wanted to create a large (1~2 million) row table of random integers for a test:
INSERT INTO test_table (num) VALUES(ROUND(RAND() * 1E6));
-- calling this will insert once for every row in test_table
INSERT INTO test_table (num)
SELECT ROUND(RAND() * 1E6)
FROM test_table;
So I quickly just kept doubling the number of rows until I had what I needed.
Supposed that you already have an arbitrary table myOldTable which is sufficiently long you could use the following trick:
set #counter = 0;
select (#counter := #counter+1), #counter*#counter from myOldTable limit 1000;
If it is that you only want to block the current thread then use select sleep(seconds); otherwise you can use a stored procedure (if there's something you want to loop over) or a UDF (user defined function).
I'm writing my first MySQL procedure. I try to generate a random number and update a value in a table with this number, but only if it doesn't exists already (due to unique constraint). My procedure looks like this:
create procedure generaterc()
begin
declare _rc char;
declare _id int;
set _id = 1;
while _id < ((select count(*) from patient) - 1) do
begin
set _rc = cast(FLOOR(1000000000 + (RAND() * 8999999999)) AS char);
select _rc;
if not exists(select * from patient where patient.rc = _rc) then
update patient set rc=_rc where id=_id;
set _id=_id+1;
end if;
end;
end while;
end
I got this error when executing the procedure: Data truncation: Data too long for column '_rc' at row 8. My rc column is varchar(255), but I guess this isn't the core of the problem. Any suggestions?
Thank you very much.
Instead of
declare _rc char;
try:
declare _rc varchar(255);
Currently _rc can only hold a single character, which is not enough to store your number.
However, for your use case you may like to take a look at the uuid_short() function. It generates a large random number that is guaranteed to be unique (subject to some rules). This way you can replace your procedure with the single statement:
update patient set rc = uuid_short();