存储过程将数据输入到表中数据和表名是动态的

时间:2018-05-27 05:18:35

标签: mysql stored-procedures

我一直在使用以下代码,我无法找到我错在哪里。我一直在运行以下代码,它在sql语法中说错误。请帮助我,我是mysql和存储过程的新手。 我得到的错误是:错误代码1064,你有SQL语法错误。

         CREATE DEFINER=`PotatoHead`@`%` PROCEDURE `InsertIntoTable`(in    
            tablename varchar(45),in ID varchar(45),in Project 
            varchar(45),in Variant varchar(45)
            in ReleaseVersion varchar(45) ,
            in TestBenchID varchar(45) ,
            in TestCaseID int(11) ,
            in TestCaseNamespace varchar(100) ,
            in TestCaseName varchar(45),
            in TestCaseDomain varchar(45) ,
            in TestType varchar(45) ,
            in HardwareVersion varchar(4000) ,
            in SoftwareVersion varchar(4000),
            in Result varchar(45) ,
            in Comment varchar(4000),
            in Duration varchar(45) ,
            in StartTime varchar(45) ,
            in EndTime varchar(45)  )
  BEGIN

  SET @sql = CONCAT('Insert into ', tablename ,' (ID,Project,Variant,
            ReleaseVersion,
            TestBenchID ,
            TestCaseID ,
            TestCaseNamespace ,
            TestCaseName ,
            TestCaseDomain ,
            TestType ,
            HardwareVersion ,
            SoftwareVersion ,
            Result ,
            Comment ,
            Duration ,
            StartTime ,
            EndTime) VALUES (');
    SET @sql = CONCAT(ID,',',Project,',',Variant,',',
    ReleaseVersion,',',
    TestBenchID,',',
    TestCaseID,',',
    TestCaseNamespace ,',',
    TestCaseName ,',',
    TestCaseDomain ,',',
    TestType ,',',
    HardwareVersion ,',',
    SoftwareVersion ,',',
    Result ,',',
    Comment ,',',
    Duration ,',',
    StartTime ,',',
    EndTime,');');
PREPARE s FROM @sql;
EXECUTE s;
DEALLOCATE PREPARE s;



 END

1 个答案:

答案 0 :(得分:1)

后输入参数列表中有一个小错字,缺少逗号
in Variant varchar(45)
                      ^^^^

这是我在Workbench

中运行代码时收到的完整错误消息
  

错误代码:1064。您的SQL语法有错误;检查   手册,对应右边的MySQL服务器版本   在ReleaseVersion varchar(45)中使用附近的语法   TestBenchID varchar(45),'在第6行

您已经删除了错误消息的部分,该部分会告诉您在引用的代码之前 之前要查找错误的位置。

另外,如果您还没有这样做,则需要在多语句过程定义之前和之后重置DELIMITER,以便MySQL知道将整个定义视为一个定义。

e.g。

DELIMITER //

CREATE DEFINER=`PotatoHead`@`%` PROCEDURE `InsertIntoTable`() 
BEGIN
  Your proc definition
END 
//

DELIMITER ;

<强>更新

最后一次更改应该已编译,所以现在我们已经进入运行时错误。我承认我没有超越原始代码的第一个错误,所以没有注意到其他一些问题。 e.g。

  • 多次分配@sql变量而不是连接
  • 由concat
  • 生成的值列表中的未加引号的字符串
  • 重复使用参数的列名称(您可以在此处使用它,但可能会导致意外结果)
  • 然而,我错过的最重要的事情就是为什么你甚至想要首先使用动态SQL来解决这个问题,除非表名要改变,否则它是不必要的。

让我们按顺序排列:

将INSERT语句的第一部分分配给@sql。没关系。稍后您将VALUES列表分配给同一个变量。此时,您将替换原始而不是连接两个部分。这导致您发布的第二个错误。你用

解决了这个问题
SET @sql = CONCAT(@sql,' VALUES(' etc.

CONCAT语句将为您留下一个包含16个未加引号的VARCHAR列变量的字符串。您需要在所有这些值周围包含单引号,否则PREPARE语句将失败。你用

解决了那个问题
SET @sql = CONCAT(@sql, '\'',
    ID,'\',\'',
    Project,'\',\'',
    Variant,'\',\'',
    ReleaseVersion,'\',\'',
    TestBenchID,'\',\'',
    TestCaseID,',',
    TestCaseNamespace ,'\',\'',

等。

CONCAT现在变得有点乱,我想你会同意。

接下来是在表中使用相同名称的参数和列名的问题。正如我之前提到的那样,在这个例子中,你可以使用它,但是当确定使用哪个参数名称时,MySQL将优先考虑参数名称,这可能会导致在SELECT,WHERE中使用参数时出现问题为了避免混淆,区分二者是一种很好的做法。所以,我还要重命名你的所有参数。 e.g。

 CREATE PROCEDURE `InsertIntoTable` (
    in _tablename varchar(45),
    in _ID varchar(45),
    in _Project varchar(45),
    in _Variant varchar(45),
    in _ReleaseVersion varchar(45) ,

然后相应地更新VALUES列表。顺便说一句,由于您的所有输入参数都是IN参数,并且这是默认值,因此您可以省去&#39; in&#39;在每一个之前,节省一些打字。

最后,您使用动态SQL。我怀疑这个过程是写入表的所有列,并且只有一个表具有这个确切的定义。如果表名不会改变,为什么需要能够在运行时更改它?如果情况并非如此,那么您有多个表存储完全相同的数据的原因是什么?如果我的怀疑是正确的,那么你可以完全放弃使用动态SQL,然后程序将变得更加简单

e.g。

CREATE PROCEDURE `InsertIntoYrTablename` (
    _ID varchar(45),
    _Project varchar(45),
    _Variant varchar(45),
    _ReleaseVersion varchar(45),
    _TestBenchID varchar(45),
    _TestCaseID int(11),
    _TestCaseNamespace varchar(100),
    _TestCaseName varchar(45),
    _TestCaseDomain varchar(45),
    _TestType varchar(45),
    _HardwareVersion varchar(4000),
    _SoftwareVersion varchar(4000),
    _Result varchar(45),
    _Comment varchar(4000),
    _Duration varchar(45),
    _StartTime varchar(45),
    _EndTime varchar(45))
  INSERT into `yrtablename` (
    ID,
    Project,
    Variant,
    ReleaseVersion,
    TestBenchID,
    TestCaseID,
    TestCaseNamespace,
    TestCaseName,
    TestCaseDomain,
    TestType,
    HardwareVersion,
    SoftwareVersion,
    Result,
    Comment,
    Duration,
    StartTime,
    EndTime
  ) VALUES (
    _ID,
    _Project,
    _Variant,
    _ReleaseVersion,
    _TestBenchID,
    _TestCaseID,
    _TestCaseNamespace,
    _TestCaseName,
    _TestCaseDomain,
    _TestType,
    _HardwareVersion,
    _SoftwareVersion,
    _Result,
    _Comment,
    _Duration,
    _StartTime,
    _EndTime);

这更容易阅读和维护,并且无需麻烦的字符串操作即可完成工作。 MySQL将负责为您引用参数,因为它现在是单个语句,因此无需BEGIN ... END块并重置DELIMITER。