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

标签 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

最佳答案

您有一个小错字,输入参数列表中缺少一个逗号

in Variant varchar(45)
                      ^^^^

这是我在工作台中运行您的代码时收到的完整错误消息

Error Code: 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 'in ReleaseVersion varchar(45) , in TestBenchID varchar(45) , ' at line 6

您删除了错误消息的一部分,该消息会告诉您在哪里查找错误,该错误将在引用的代码之前

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

例如

DELIMITER //

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

DELIMITER ;

更新

最后的更改应该已编译,因此现在我们遇到运行时错误。我承认我没有关注原始代码中的第一个错误,因此没有注意到其他一些问题。例如

  • 对@sql变量进行多次赋值而不是串联
  • 由 concat 产生的值列表中不带引号的字符串
  • 重复使用参数的列名称(您可以在这里使用它,但可能会导致意外结果)
  • 但是,我错过的一件大事是,为什么您一开始就想使用动态 SQL 来解决这个问题,除非表名要更改,否则没有必要。

让我们按顺序排列:

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

来修复它
SET @sql = CONCAT(@sql,' VALUES(' etc.

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

来修复这个问题
SET @sql = CONCAT(@sql, '\'',
    ID,'\',\'',
    Project,'\',\'',
    Variant,'\',\'',
    ReleaseVersion,'\',\'',
    TestBenchID,'\',\'',
    TestCaseID,',',
    TestCaseNamespace ,'\',\'',

等等。

CONCAT 现在变得有点困惑,我想你会同意的。

接下来的问题是对参数和表中的列名称使用相同的名称。正如我之前提到的,在这种情况下你会侥幸逃脱,但是当 MySQL 确定使用哪个参数时,它会优先考虑参数名称而不是列名称,这在 SELECT、WHERE 子句中使用参数时可能会导致问题,等等。最好区分两者以避免混淆。因此,我还会重命名您的所有参数。例如

 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 参数,并且这是默认设置,因此您可以省去每个参数前面的 'in' 并节省一些打字时间。

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

例如

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 block 并重置 DELIMITER。

关于mysql - 将数据输入到数据和表名是动态的表中的存储过程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50549244/

相关文章:

mysql - Knex 创建数据库并向其中插入数据

mysql - 如何使通配符考虑之间的空格

postgresql - 为什么 PostgreSQL 在从稳定函数调用 volatile 函数时不给出警告?

mysql - 查找 Mysql 存储过程中的错误。无法理解错误

sql - 从 SELECT 语句更新列

mysql - Mysql中通过注释选择存储过程名称

mysql - 简短的 sql 挑战,结果集上有多个下一行,带有 group by 和 count

mysql - mysql查询中缺少数据,内部连接需要条件语句

sql-server - 创建带有空值参数的存储过程

php - 无法分配使用 php 获取的变量