【问题标题】:How to create a stored procedure in MySQL with Knex raw如何使用 Knex raw 在 MySQL 中创建存储过程
【发布时间】:2021-07-28 07:27:39
【问题描述】:

我正在使用 Adonis,它在引擎盖下使用了 Knex。我想创建这个存储过程


DROP PROCEDURE IF EXISTS fill_date_dimension;
DELIMITER //
CREATE PROCEDURE fill_date_dimension(IN startdate DATE,IN stopdate DATE)
BEGIN
    DECLARE currentdate DATE;
    SET currentdate = startdate;
    WHILE currentdate < stopdate DO
        INSERT INTO time_dimension VALUES (
                        YEAR(currentdate)*10000+MONTH(currentdate)*100 + DAY(currentdate),
                        currentdate,
                        YEAR(currentdate),
                        MONTH(currentdate),
                        DAY(currentdate),
                        QUARTER(currentdate),
                        WEEKOFYEAR(currentdate),
                        DATE_FORMAT(currentdate,'%W'),
                        DATE_FORMAT(currentdate,'%M'),
                        'f',
                        CASE DAYOFWEEK(currentdate) WHEN 1 THEN 't' WHEN 7 then 't' ELSE 'f' END,
                        NULL);
        SET currentdate = ADDDATE(currentdate,INTERVAL 1 DAY);
    END WHILE;
END
//
DELIMITER ;

TRUNCATE TABLE time_dimension;

CALL fill_date_dimension('2018-01-01','2030-12-31');
OPTIMIZE TABLE time_dimension;

问题是 knex raw,或者可能是 Adonis(我不知道)会去掉换行符。这给了我错误

DROP PROCEDURE IF EXISTS fill_date_dimension; DELIMITER // CREATE PROCEDURE fill_date_dimension(IN startdate DATE,IN stopdate DATE) BEGIN DECLARE currentdate DATE; SET currentdate = startdate; WHILE currentdate < stopdate DO INSERT INTO dates VALUES ( YEAR(currentdate)*10000+MONTH(currentdate)*100 + DAY(currentdate), currentdate, YEAR(currentdate), MONTH(currentdate), DAY(currentdate), QUARTER(currentdate), WEEKOFYEAR(currentdate), DATE_FORMAT(currentdate,'%W'), DATE_FORMAT(currentdate,'%M'), 'f', CASE DAYOFWEEK(currentdate) WHEN 1 THEN 't' WHEN 7 then 't' ELSE 'f' END, NULL); SET currentdate = ADDDATE(currentdate,INTERVAL 1 DAY); END WHILE; END // DELIMITER ; TRUNCATE TABLE dates; CALL fill_date_dimension('2018-01-01','2030-12-31'); OPTIMIZE TABLE time_dimension; - ER_PARSE_ERROR: 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 // CREATE PROCEDURE fill_date_dimension(IN startdate DATE,IN sto' at line 4

我曾尝试将自己的 \n 标记放入 SQL 中,但它们被删除了。

任何想法让 knex.raw 运行我给它的东西,而不是取出标签。

【问题讨论】:

    标签: mysql stored-procedures knex.js


    【解决方案1】:

    原来问题与客户端无关,而与无法在一行中接受多个命令的数据库引擎有关。

    最后,我找到了一种不使用过程来做同样事情的不同方法,但我不得不像这样将每一行代码作为单独的命令执行。

    await db.raw(`DROP TABLE IF EXISTS numbers_small;`)
        await db.raw(`DROP TABLE IF EXISTS numbers_small;`)
        await db.raw(`CREATE TABLE numbers_small (number INT);`)
        await db.raw(`INSERT INTO numbers_small VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);`)
        await db.raw(`DROP TABLE IF EXISTS numbers;`)
        await db.raw(`CREATE TABLE numbers (number BIGINT);`)
        await db.raw(`INSERT INTO numbers
        SELECT thousands.number * 1000 + hundreds.number * 100 + tens.number * 10 + ones.number
          FROM numbers_small thousands, numbers_small hundreds, numbers_small tens, numbers_small ones
        LIMIT 1000000;`)
        await db.raw(`DROP TABLE IF EXISTS dates;`)
        await db.raw(`CREATE TABLE dates (
          date_id          BIGINT PRIMARY KEY, 
          date             DATE NOT NULL,
          timestamp        BIGINT, 
          weekend          CHAR(10) NOT NULL DEFAULT "Weekday",
          day_of_week      CHAR(10),
          month            CHAR(10),
          month_day        INT, 
          year             INT,
          week_starting_monday CHAR(2),
          UNIQUE KEY date (date),
          KEY year_week (year,week_starting_monday)
        );`)
        await db.raw(`INSERT INTO dates (date_id, date)
        SELECT number, DATE_ADD( '2016-01-01', INTERVAL number DAY )
          FROM numbers
          WHERE DATE_ADD( '2016-01-01', INTERVAL number DAY ) BETWEEN '2016-01-01' AND '2030-01-01'
          ORDER BY number;`)
        await db.raw(`UPDATE dates SET
        timestamp =   UNIX_TIMESTAMP(date),
        day_of_week = DATE_FORMAT( date, "%W" ),
        weekend =     IF( DATE_FORMAT( date, "%W" ) IN ('Saturday','Sunday'), 'Weekend', 'Weekday'),
        month =       DATE_FORMAT( date, "%M"),
        year =        DATE_FORMAT( date, "%Y" ),
        month_day =   DATE_FORMAT( date, "%d" );`)
        await db.raw(`UPDATE dates SET week_starting_monday = DATE_FORMAT(date,'%v');`)
    

    【讨论】:

    • 我只是好奇,是为了“安全”吗?如果是这样,如果在查询中添加“\n”或“\r\n”会发生什么?
    【解决方案2】:

    这应该会有所帮助。在这里,我编写了 knex-migrate 期望的模块。适应你的需要应该不难。

    const mysql = require('mysql2');
    
    const {
      database: {
        connection: {
          host, user, password, database, port
        }
      }
    } = require('./settings.js');
    
    exports.up = async () => {
      const script = `
        CREATE DEFINER=\`<YOUR_DB_USER>\`@\`%\` PROCEDURE \`fill_date_dimension\`(IN startdate DATE,IN stopdate DATE)
        BEGIN
            DECLARE currentdate DATE;
            SET currentdate = startdate;
            WHILE currentdate < stopdate DO
            INSERT INTO time_dimension VALUES (
                            YEAR(currentdate)*10000+MONTH(currentdate)*100 + DAY(currentdate),
                            currentdate,
                            YEAR(currentdate),
                            MONTH(currentdate),
                            DAY(currentdate),
                            QUARTER(currentdate),
                            WEEKOFYEAR(currentdate),
                            DATE_FORMAT(currentdate,'%W'),
                            DATE_FORMAT(currentdate,'%M'),
                            'f',
                            CASE DAYOFWEEK(currentdate) WHEN 1 THEN 't' WHEN 7 then 't' ELSE 'f' END,
                            NULL);
            SET currentdate = ADDDATE(currentdate,INTERVAL 1 DAY);
            END WHILE;
        END`
    
      const connection = mysql.createConnection({
        host,
        user,
        database,
        password,
        port
      });
    
      return new Promise(function (resolve, reject) {
        connection.query(
          script,
          function (err) {
            if (err) {
              return reject(err);
            }
    
            return resolve();
          }
        );
      });
    };
    
    exports.down = async knex => knex.raw('DROP PROCEDURE IF EXISTS fill_date_dimension');
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-10
      • 1970-01-01
      • 2021-09-30
      相关资源
      最近更新 更多