Node.js项目中kysely-codegen生成SQL Server 2012类型失败+Kysely SQL编译异常求助
我来帮你梳理下这两个问题的排查方向和可能的解决办法,你可以一步步尝试:
一、kysely-codegen生成类型时的UnhandledPromiseRejection错误
你遇到的UnhandledPromiseRejection: [object Array]错误,本质是kysely-codegen在 introspect 数据库时抛出了数组形式的错误,但没有被捕获。因为错误信息被隐藏成了[object Array],我们需要先拿到具体错误内容,再针对性解决。
可能的原因及排查步骤:
连接字符串的实例名称不一致
你在kysely-codegen配置里用的是Server=localhost,1433,但在项目代码里用的是localhost\\SQLEXPRESS——如果你的SQL Server是默认的SQLEXPRESS实例,直接指定端口1433可能找不到实例(除非你手动修改过实例的端口配置)。- 解决:修改
./.kysely-codegenrc.json里的连接字符串,把Server改成和代码一致的写法:"url": "Server=localhost\\SQLEXPRESS;Database=MedicalWEB;User Id=root;Password=root;Encrypt=false;TrustServerCertificate=true;" - 改完后重新执行
npx kysely-codegen --config-file ./.kysely-codegenrc.json试试。
- 解决:修改
手动捕获具体错误内容
直接用npx命令看不到具体的错误数组,我们可以写一个简单的脚本调用kysely的introspect功能,手动捕获错误:- 创建
introspect-test.js文件:const { MssqlDialect } = require('kysely/dialects/mssql'); const { ConnectionPool } = require('mssql'); async function testIntrospection() { try { const dialect = new MssqlDialect({ tarn: { options: { min: 0, max: 10 } }, tedious: { connectionFactory: () => new ConnectionPool({ authentication: { type: 'default', options: { userName: 'root', password: 'root' } }, server: 'localhost\\SQLEXPRESS', database: 'MedicalWEB', port: 1433, encrypt: false, trustServerCertificate: true }) } }); const introspector = dialect.createIntrospector(); const metadata = await introspector.getIntrospectionMetadata(); console.log('Introspection success! Metadata preview:', { tables: metadata.tables.map(t => t.name) }); } catch (err) { console.error('Introspection failed with detailed error:', err); } } testIntrospection(); - 执行
node introspect-test.js,就能看到具体的错误信息(比如是系统表权限不足,还是SQL Server版本兼容问题)。
- 创建
SQL Server 2012的兼容性问题
SQL Server 2012是比较老旧的版本(2012年发布,已经停止主流支持),kysely-codegen的mssql dialect可能依赖了SQL Server 2016+的系统视图或语法。- 如果手动脚本的错误是系统视图不存在或语法不支持,你可以尝试:
- (如果可行)升级SQL Server到2016或以上版本;
- 查看kysely-codegen的GitHub issues,有没有其他用户遇到过SQL Server 2012的兼容问题,是否有临时补丁或配置项可以调整。
- 如果手动脚本的错误是系统视图不存在或语法不支持,你可以尝试:
数据库权限不足
Introspect需要读取SQL Server的系统表(比如sys.tables、sys.columns、sys.schemas等),如果你的用户没有权限访问这些对象,会导致 introspect 失败。- 给用户授予
VIEW DEFINITION权限:USE MedicalWEB; GRANT VIEW DEFINITION ON DATABASE::MedicalWEB TO root;
- 给用户授予
二、Kysely默认用PostgreSQL编译SQL的异常
你提到Kysely会把SQL编译成PostgreSQL风格,这说明Kysely没有正确加载MssqlDialect,或者在代码中有配置错误。
排查步骤:
确认依赖安装完整
Kysely的mssql dialect依赖tedious和mssql包,确保你已经安装了所有必要依赖:npm install kysely tedious mssql检查Dialect的导入和实例化是否正确
确保你没有误导入PostgresDialect,并且正确创建MssqlDialect实例:// 正确导入路径 const { Kysely } = require('kysely'); const { MssqlDialect } = require('kysely/dialects/mssql'); // 注意是kysely/dialects/mssql const { ConnectionPool } = require('mssql'); async function initDb() { try { const dialect = new MssqlDialect({ tarn: { options: { min: 0, max: 10 } }, tedious: { connectionFactory: () => new ConnectionPool({ authentication: { type: 'default', options: { userName: process.env.DB_USER, password: process.env.DB_PWD } }, server: 'localhost\\SQLEXPRESS', database: process.env.DB_NAME, port: 1433, encrypt: false, trustServerCertificate: true }) } }); const db = new Kysely({ dialect }); // 测试:执行一个简单的查询,看生成的SQL是否是MSSQL风格 const testResult = await db .selectFrom('your_table_name') .select(['column1', 'column2']) .limit(1) // MSSQL会自动转换成TOP 1 .execute(); console.log('Test query executed successfully:', testResult); return db; } catch (err) { console.error('DB init failed:', err); throw err; } }注意:Kysely的MssqlDialect会自动把
limit(1)转换成MSSQL的TOP 1语法,如果生成的SQL还是PostgreSQL的LIMIT 1,说明Dialect没有正确加载。检查是否有代码覆盖DB实例
确认项目中没有其他地方重新定义了db变量,或者使用了中间件/插件强制切换了Dialect。
内容来源于stack exchange

