如何使sequelize在其SQL语句中的Unicode字符串之前添加N?

Ran*_* Yu 6 database sql-server unicode node.js sequelize.js

我是Sequelize.js和Node.js的新手,我们的后端数据库是SQL Server 2014,所以我们使用Sequelize.js作为ORM层,我们需要处理数据中的非英语字符.

当我尝试使用sequelize create方法插入非英文字符时,我只进入???DB,调试后我发现原因如下,但我不知道是否有任何现有的好解决方案来修复它.

下面是我在我的应用程序中创建的一个测试模型,我将使用sequelize.import方法生成表模式,然后调用fillTestData方法在我对DB服务器调用sync之后将测试数据插入到DB中,但是我只获得了很多'????'在DB表中.

var Promise = require("sequelize").Promise;

module.exports = function(sequelize, DataTypes) {
  var Test = sequelize.define("Test", {
    ID: {
      type: DataTypes.BIGINT,
      primaryKey: true,
      autoIncrement: true
    },

    Name: {
      type: DataTypes.STRING(255),
      allowNull: true
    }
  }, {
    charset: "utf8",
    classMethods: {
      fillTestData: function(models) {

        return Promise.join(
          Test.create({Name: "hello"}),
          Test.create({Name: "aello"}),
          Test.create({Name: "Aello"}),
          Test.create({Name: "bello"}),
          Test.create({Name: "?????"}),
          Test.create({Name: "?????"}),
          Test.create({Name: "????????"}),
          Test.create({Name: "??????????"}),
          Test.create({Name: "Hallå"}),
          Test.create({Name: "??"}),
          Test.create({Name: "??"}),
          Test.create({Name: "???, ?????"}),
          Test.create({Name: "???? ??????"}),
          Test.create({Name: "ENLE o gbogbo eniyan"}),
          Test.create({Name: "??? ?? ???????"}));
      }
    }
  });


  return Test;
};
Run Code Online (Sandbox Code Playgroud)

我检查了Node.js的输出日志,发现sequelize上面的创建请求转换成下面的SQL语句:

INSERT INTO [Test] ([Name]) OUTPUT INSERTED.* VALUES ('??');
Run Code Online (Sandbox Code Playgroud)

我在Database中检查了Column定义,Name列是nvarchar,我可以使用下面的SQL语句将正确的非英语数据插入到DB中:

  insert into [Test] values (N'??')
Run Code Online (Sandbox Code Playgroud)

然后我意识到,sequelize不要在SQL语句中的非英语字符串之前添加'N'.

然后我尝试调试并找到"sequelize\lib\sql-string.js"文件中的根本原因,sequelize将escapeId在生成SQL语句之前调用其方法来转义值,在此方法中,它不会检查是否需要在mssql dialect的Unicode字符串之前添加'N'.所以我最后对这个方法做了一点改动,如下所示:

  if(dialect === 'mssql') {
    return "N'" + val + "'";
  }
  else {
    return "'" + val + "'";    
  }
Run Code Online (Sandbox Code Playgroud)

然后我重新运行我的应用程序,一切都可以按我的期望工作,所有Unicode字符串现在可以正确存储到数据库.

但这不是一个好的解决方案,我希望sequelize应该考虑这种要求并提供某种定义选项,如charset,所以我不需要自己照顾这个.

有人碰巧知道如何优雅地解决这个问题吗?

dig*_*ron 0

根据 Microsoft ( https://msdn.microsoft.com/en-us/library/ms186939.aspx ) 的说法,nchar 和 nvarchar 都使用 UNICODE UCS-2 字符集。尝试在测试模型代码中将字符集从 utf8 更改为 UCS-2。