2016-12-02 10 views
0

私が達成したいのは、テーブル内のすべての不足しているIDのレコードセットを返すストアドプロシージャです。たとえば :そこに処理することができ、複数のテーブルがあるので、私はメンテナンスを必要とするだけで1つのストアドプロシージャを持っていると、そうであろうと変数テーブル名を持つMySQLストアドプロシージャと不足しているレコードの取得

---------- 
| result | 
---------- 
| 3  | 
| 4  | 
| 6  | 
| 7  | 
| 8  | 
| 9  | 
---------- 

注:

-------------------- 
| games   | 
-------------------- 
| id | game name | 
-------------------- 
| 1 | first game | 
| 2 | second game | 
| 5 | fifth game | 
| 10 | tenth game | 
------------------- 

これが生じるはずですテーブル名は動的に追加する必要があります。

私はストアドプロシージャのプリペアドステートメント、パラメータ、ループに関するチュートリアルをいくつか見つけましたが、その組み合わせは動作しません。

Iを適用する心を持っているロジックは次のとおりです。

  1. は、テーブルをテーブル内の
  2. ループの最高のIDを取得していない場合、イテレータはID
  3. として存在しているかどうかを確認、

このに行われルーピング後に結果セットを結果セットに追加して、戻ることは、私がこれまでに得たものである:

CREATE DEFINER=`root`@`localhost` PROCEDURE `get_missing_ids`(IN in_kind varchar(15), OUT out_result int) 
BEGIN 
    DECLARE highest_id INT; 
    DECLARE i INT; 
    DECLARE check_id INT; 

    SET @highestid = CONCAT("(CALL get_highest_id('", in_kind, "',@id)"); 
    PREPARE stmt1 FROM @highestid; 
    SET highest_id = (EXECUTE stmt1); 

    WHILE i < highest_id DO 
     SET @checkid = CONCAT("SELECT COUNT(*) FROM ", in_kind, " WHERE id = ", i, ")"); 
     PREPARE stmt2 FROM @checkid; 
     SET check_id = (EXECUTE stmt2); 
     IF check_id = 0 THEN 
      SELECT i; 
     END IF; 
    END WHILE;  
END 

私はこのコンボをどのように機能させることができますか?

+1

あなたがこれまでに – Drew

+0

を持っていない私はここので、それに – Drew

+0

@Drewをしてください私の仕様ですので、オフトピックとして、この質問を閉じるために投票しています何、私は現在、十分な – stijnpiron

答えて

0

実際にループする必要はありません。順序付けられた番号を含む一時的な(または固定の)表でソース表を結合し、それらを比較するだけです。

このテーブルのテーブル名とIDを使用するストアドプロシージャとして作成するには、このストアドプロシージャを実行してください。それは私の作品です。

delimiter $$ 

use `test`$$ 

drop procedure if exists `FindMissedID`$$ 

create definer=`root`@`localhost` procedure `FindMissedID`(tableName varchar(100), tableNameID varchar(100)) 
begin 

-- Create temporary table containing number for comparing source table 
drop table if exists ListOfNumber; 
create temporary table ListOfNumber(
    number int, 
    primary key (number) 
) 
engine = innodb; 

-- Generate some numbers. Make it fit your needs 
insert into ListOfNumber 
    select @row := @row + 1 as row from 
    (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) tens, 
    (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) hundreds, 
    (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) thousands, 
    -- etc 
    (select @row:=0) r; 

-- Make a prepared statement 
set @SQL = concat("select ListOfNumber.number as MissingID" 
     , char(10), "from ", tableName 
     , char(10), "right join ListOfNumber on ", tableName, ".", tableNameID, " = ListOfNumber.number" 
     , char(10), "where ", tableName, ".", tableNameID, " is null" 
     , char(10), "order by ListOfNumber.number" 
      ); 

-- Execute statement     
prepare statement from @SQL; 
execute statement; 
deallocate prepare statement;    

end$$ 

delimiter ; 

試してください。

+0

これは近づいていますが、 IDはそのテーブルからチェックされ、私はそれのための別のストアドプロシージャを持っています:get_highest_id(in_tablename、out_highestid)。 それはどうしたらうまくいくのですか? – stijnpiron

+0

Btw、なぜ最高のIDを探したいですか?私はそのSPを試して、それは私のテーブルから欠落IDのすべてを表示するだけで、テンポラリテーブルの最大数があなたのテーブルの最大IDよりも高いことを確認する必要があります。これで十分に問題が解決されない場合は、詳細を教えてください。 – Hermanto

+0

理由は次のとおりです。現時点では、1つのテーブルは300レコード長にすることができますが、4000年(たとえば)以内に、これは、この時点で最大idが320 4100年(レコードが100個欠けている)。この時点で存在する最大のidからゼロまでの範囲のすべての欠落した数字のリストが必要です。私が知りたいと思っていないと最大のIDの長さを入力する私は十分な自分自身を明確にすることができます場合は、IDの行方不明を確認する – stijnpiron

0

thisからいくつかのヒントを使用して、あなたが不足しているのIDを見つけるために、単一のクエリを使用することができます。

DELIMITER // 
CREATE PROCEDURE `get_missing_ids`() 
BEGIN 

    SELECT (t1.id + 1) as missing_starts_at, 
      (SELECT MIN(t3.id) -1 
      FROM games t3 
      WHERE t3.id > t1.id 
      ) as missing_ends_at 
    FROM games t1 
    WHERE NOT EXISTS (SELECT t2.id 
         FROM games t2 
         WHERE t2.id = t1.id + 1) 
    HAVING missing_ends_at IS NOT NULL; 
END// 

範囲として持つ行を返します。

call `get_missing_ids`(); 
+-------------------+-----------------+ 
| missing_starts_at | missing_ends_at | 
+-------------------+-----------------+ 
|     3 |    4 | 
|     6 |    9 | 
+-------------------+-----------------+ 

今、あなたはその値を使用することができます。

関連する問題