0

MySQLでカーソルとプロシージャを扱うのはこれが初めてです。カーソルとroseindia.netのMySQLドキュメントに記載されている例に従いましたが、エラーが発生しました。

列数が行1の値数と一致しません

関連するテーブルは次のとおりです(テーブルはまだ3NFに正規化されていないため、受け取った時点で、artists.nameの代わりにartists.idを使用する必要があることに気付きました):

CREATE TABLE `user_artists_rankings` (
  `user_id` varchar(50) NOT NULL DEFAULT '' COMMENT 'kpop_users.user_id',
  `artist_name` varchar(100) NOT NULL,
  `calculated_score` int(11) DEFAULT NULL,
  `last_calculated_score_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`user_id`,`artist_name`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE `kpop_users` (
  `user_id` char(50) NOT NULL,
  `username` char(150) DEFAULT '',
  `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`user_id`) USING BTREE,
  KEY `name_idx` (`username`),
  KEY `twitter_id_idx` (`twitter_user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
CREATE TABLE `artists` (
  `name` varchar(100) NOT NULL,
  `type` varchar(45) DEFAULT NULL,
  `official_twitter_screenname` varchar(45) DEFAULT NULL,
  `thumbnail_url` varchar(500) DEFAULT NULL,
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`),
  KEY `Index_2` (`official_twitter_screenname`)
) ENGINE=InnoDB AUTO_INCREMENT=164 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

目的は、テーブルにuser-artist(n)行user_artists_rankingsを含めることです。つまり、次のようになります。

user1 | artist1
user1 | artist2
user1 | artist3
user2 | artist1
user2 | artist2
user2 | artist3

これが私が作成した手順です:

delimiter ;
drop procedure if exists testrun;
delimiter //
create procedure testrun()
begin
    declare d int default 0;
    declare user_id varchar(50);
    declare artist_name varchar(100);
    declare cur_users cursor for select user_id from kpop_users;
    declare cur_artists cursor for select name from artists;
    declare continue handler for sqlstate '02000' set d=1;
    declare continue handler for sqlstate '23000' set d=1;
    open cur_users;
    open cur_artists;
    lbl1: loop 
        if d=1 then 
            leave lbl1;
        end if;
        if not d=1 then
            fetch cur_users into user_id;
            lbl2: loop
                if d=1 then
                    leave lbl2;
                end if;
                if not d=1 then
                    fetch cur_artists into artist_name;
                    insert into user_artists_rankings values (user_id, artist_name);
                end if;
            end loop lbl2;
        end if;
    end loop lbl1;
    close cur_users;
    close cur_artists;
end
//
delimiter ;
call testrun();

どんな助けでも大歓迎です。ありがとうございました。

4

2 に答える 2

1

このコード行は間違っています:

insert into user_artists_rankings values (user_id, artist_name);

テーブルには 4 つのフィールドがあり、そのうちの 2 つだけを INSERT に使用しているため、使用するフィールドを指定する必要があります。そのはず:

insert into user_artists_rankings(`user_id`, `artist_name`) VALUES(user_id, artist_name);
于 2012-09-09T12:37:02.350 に答える
0

@Jocelynが助けてくれたINSERTステートメントでの最初のブーブーの後、ネストされたループが間違っていることがわかりました。ネストされたループにも別のラベルを付ける必要があります。修正されたループは次のとおりです。

delimiter ;
DROP procedure IF EXISTS firstrunUser_Artists_Rankings;
delimiter //
CREATE PROCEDURE firstrunUser_Artists_Rankings()
block1: BEGIN
    DECLARE d INT DEFAULT 0;
    DECLARE new_user_id VARCHAR(50);
    DECLARE new_artist_id INT(10);
    DECLARE cur_users CURSOR FOR SELECT `user_id` FROM kpop_users;
    DECLARE cur_artists CURSOR FOR SELECT `id` FROM artists;
    DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET d=1;
    DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET d=1;
    OPEN cur_users;
    lbl1: LOOP 
        IF d=1 THEN
         SHOW ERRORS;
            LEAVE lbl1;
        END IF;
        IF NOT d=1 THEN
            FETCH cur_users INTO new_user_id;
            block2: BEGIN
             DECLARE e INT DEFAULT 0;
             DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET e=1;
       DECLARE CONTINUE HANDLER FOR SQLSTATE '23000' SET e=1;
             OPEN cur_artists;
             lbl2: LOOP
                 IF e=1 THEN
                     LEAVE lbl2;
                 END IF;
                 IF NOT e=1 THEN
                     FETCH cur_artists INTO new_artist_id;
                     INSERT INTO user_artists_rankings(`user_id`, `artist_id`) VALUES (new_user_id, new_artist_id);
                     INSERT INTO user_artists_rankings_raw(`user_id`, `artist_id`) VALUES (new_user_id, new_artist_id);
                 END IF;
             END LOOP lbl2;
             CLOSE cur_artists;
            END block2;
        END IF;
    END LOOP lbl1;
    CLOSE cur_users;
END block1;
//
delimiter ;
CALL firstrunUser_Artists_Rankings();
于 2012-09-10T07:34:10.870 に答える