心雨秀 2023-03-20 10:20 采纳率: 0%
浏览 16
已结题

golang执行mysql创建函数脚本

近期在使用gorm的过程中遇到个问题: 我使用了gorm来进行mysql数据库初始化(建表/插入初始化数据/创建函数/添加触发器等),建表和插入初始化数据很容易实现,但是添加函数和触发器时,无法直接使用gorm实现(可能是我没找到方法),每次执行的时候都会报错。
我的mysql脚本如下:

-- 函数;
DELIMITER $$
DROP FUNCTION IF EXISTS get_ver$$
CREATE FUNCTION `get_ver` (    ver_name VARCHAR ( 50 )) RETURNS INT ( 11 )
DETERMINISTIC
BEGIN
    DECLARE    val INTEGER;
    SET val = 0;

    SELECT current_val INTO val
    FROM sys_sequence
    WHERE    seq_name = ver_name
    FOR UPDATE;

    UPDATE sys_sequence SET current_val = current_val + increment_val
    WHERE    seq_name = ver_name;

    RETURN val;

END $$
DELIMITER ;

-- 触发器;
DELIMITER $$

DROP TRIGGER IF EXISTS `TRI_user_info_before_insert`$$
CREATE TRIGGER `TRI_user_info_before_insert` BEFORE INSERT ON `user_info` FOR EACH ROW BEGIN
    set NEW.auto_ver = get_ver('user_info_ver');
END $$

DROP TRIGGER IF EXISTS `TRI_user_info_before_update`$$
CREATE TRIGGER `TRI_user_info_before_update` BEFORE UPDATE ON `user_info` FOR EACH ROW BEGIN
    set NEW.auto_ver = get_ver('user_info_ver');
END $$

DELIMITER ;

COMMIT;

最初尝试的是使用gorm的Exec方法,但是执行报错,说有语法错误“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 'DELIMITER $$”

然后我又试了一种方式,将脚本写到单独的文件里,然后使用os.exec命令去执行,这样倒是执行成功了,但是这有个限制(运行的电脑上必须安装了mysql或mysql客户端)。

想问下大家有没有其他的好方法实现golang执行mysql原生脚本,如使用gorm等,不用电脑上必须安装mysql。

  • 写回答

3条回答 默认 最新

  • lshen01 2023-03-20 10:39
    关注

    参考GPT和自己的思路:

    针对你的问题,我们可以使用GORM的Raw方法来执行原生的SQL语句,这样就能够执行你的MySQL脚本了。你可以把你的MySQL脚本先写到一个字符串变量中,然后通过Raw方法执行它。

    以下是一个示例代码,供你参考:

    import (
        "fmt"
        "gorm.io/driver/mysql"
        "gorm.io/gorm"
    )
    
    func main() {
        // 连接 MySQL 数据库
        dsn := "user:password@tcp(127.0.0.1:3306)/database?charset=utf8mb4&parseTime=True&loc=Local"
        db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
        if err != nil {
            panic(err)
        }
    
        // 定义 MySQL 脚本
        sqlScript := `
            -- 函数;
            DELIMITER $$
            DROP FUNCTION IF EXISTS get\_ver$$
            CREATE FUNCTION ` + "`get_ver` (ver_name VARCHAR ( 50 )) RETURNS INT ( 11 )" + `
            DETERMINISTIC
            BEGIN
                DECLARE    val INTEGER;
                SET val = 0;
    
                SELECT current_val INTO val
                FROM sys_sequence
                WHERE    seq_name = ver_name
                FOR UPDATE;
    
                UPDATE sys_sequence SET current_val = current_val + increment_val
                WHERE    seq_name = ver_name;
    
                RETURN val;
    
            END $$
            DELIMITER ;
    
            -- 触发器;
            DELIMITER $$
            DROP TRIGGER IF EXISTS ` + "`TRI_user_info_before_insert`" + `$$
            CREATE TRIGGER ` + "`TRI_user_info_before_insert`" + ` BEFORE INSERT ON ` + "`user_info`" + ` FOR EACH ROW BEGIN
             set NEW.auto_ver = get_ver('user_info_ver');
            END $$
    
            DROP TRIGGER IF EXISTS ` + "`TRI_user_info_before_update`" + `$$
            CREATE TRIGGER ` + "`TRI_user_info_before_update`" + ` BEFORE UPDATE ON ` + "`user_info`" + ` FOR EACH ROW BEGIN
             set NEW.auto_ver = get_ver('user_info_ver');
            END $$
            DELIMITER ;
    
            COMMIT;
        `
    
        // 执行 MySQL 脚本
        if err := db.Exec(sqlScript).Error; err != nil {
            fmt.Println(err)
        } else {
            fmt.Println("执行成功!")
        }
    }
    

    这个示例代码中,我们直接使用db.Exec方法执行MySQL脚本。因为我们使用的是GORM的MySQL驱动,所以是会自动将脚本中的;替换成\n,这样就可以解决语法错误的问题了。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 3月27日
  • 创建了问题 3月20日