代码之家  ›  专栏  ›  技术社区  ›  Lizard

mysql变量-set@var

  •  1
  • Lizard  · 技术社区  · 14 年前

    我正在尝试创建一个MySQL代码段,该代码段将分析表并删除重复条目(重复项基于两个字段,而不是整个记录)

    我有以下代码,当我硬编码查询中的变量时可以使用,但是当我将它们取出并作为变量放入时,我会得到MySQL错误,下面是脚本:

    SET @tblname = 'mytable';
    SET @fieldname = 'myfield';
    SET @concat1 = 'checkfield1';
    SET @concat2 = 'checkfield2';
    
    ALTER TABLE @tblname ADD `tmpcheck` VARCHAR( 255 ) NOT NULL;
    
    UPDATE @tblname SET `tmpcheck` = CONCAT(@concat1,'-',@concat2);
    
    CREATE TEMPORARY TABLE `tmp_table` (
    `tmpfield` VARCHAR( 100 ) NOT NULL
    ) ENGINE = MYISAM ;
    
    INSERT INTO `tmp_table` (`tmpfield`) SELECT @fieldname FROM @tblname GROUP BY `tmpcheck` HAVING ( COUNT(`tmpcheck`) > 1 );
    
    DELETE FROM @tblname WHERE @fieldname IN (SELECT `tmpfield` FROM `tmp_table`);
    
    ALTER TABLE @tblname DROP `tmpcheck`;
    

    我收到以下错误:

    #1064 - 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 '@tblname ADD `tmpcheck` VARCHAR( 255 ) NOT NULL' at line 1 
    

    这是因为我不能为表名使用变量吗?还有什么可能是错误的,或者我如何解决这个问题。

    3 回复  |  直到 12 年前
        1
  •  2
  •   bobince    14 年前

    这是因为我不能为表名使用变量吗?

    是的,或者其他模式名,如列。字符串变量只能在MySQL需要 ' -引用字符串。

    如果确实需要这样做,您可以使用__dynamic sql_:将整个查询创建为字符串,并将 @tblname 在那个时候放入字符串,并使用 EXECUTE . 这非常难看,如果不小心,可能会导致SQL注入,因此如果有其他选项,请避免使用它。

    从MyTable Group By中选择MyField tmpcheck 有(计数) TMP-CHECK (1)

    这对我来说似乎有问题。除非 myfield 功能依赖于 TMP-CHECK (阿法克斯不能,就像 TMP-CHECK 不是主键),这不是有效的ANSI SQL。MySQL会让您摆脱困境,但您会说的是,对于共享值为 TMP-CHECK 挑选 fieldname 从那一组的一排 随意地 以后删除__。这真的是你想要的吗?我希望你删除 除了一个以外 重复的。

    通常不需要这种复杂的过程来删除重复项。只需使用删除联接:

    DELETE my0
    FROM mytable AS my0
    JOIN mytable AS my1
        ON my1.checkfield1=my0.checkfield1 AND my1.checkfield2=my0.checkfield2
        AND my1.id>my0.id;
    

    这是假设 id 可订购和 UNIQUE 这样你就可以决定坐哪一排了 身份证件 ) 迈菲尔德 可能是那个领域,但我不能从上下文中分辨出来。

        2
  •  1
  •   Matti Virkkunen    14 年前

    为表名使用变量确实是非法的。您必须将SQL生成为字符串并使用 the prepared statement feature 执行它。

        3
  •  0
  •   Lizard    14 年前

    我使用了两种答案的组合:

    SET @tblname = 'myTable';
    SET @idfield = 'myPrimaryKey';
    SET @check1 = 'field1';
    SET @check2 = 'field2';
    
    SET @q1 = CONCAT('DELETE my0 FROM `',@tblname, '` AS my0 JOIN `',@tblname, '` AS my1 ON my1.',@check1,' = my0.',@check1,' AND my1.',@check2,' = my0.',@check2,' AND my1.',@idfield,' > my0.',@idfield,'');
    PREPARE stmt1 FROM @q1;
    EXECUTE stmt1;
    DEALLOCATE PREPARE stmt1;