MatLab SQLite读取列首为NaN的字段时报错求助
MatLab SQLite查询报错:列首为NaN时
fetch执行失败 问题现象
使用MatLab的sqlwrite创建SQLite数据库和数据表后,执行fetch查询时:
- 若某列的首行值为NaN,查询该列时会抛出错误
- 若NaN不在列首,即使列中存在其他NaN,查询也能正常完成
报错信息
Error using matlab.depfun.internal.database.SqlDbConnector/fetchRows Unexpected NULL; (zero-based) column index: 0. Details: [initVecVarVecFromSqldbTypes]. Error in sqlite/fetchHook Error in database.relational.connection/fetch (line 234) data = fetchHook(connect,second_input,optsObject,isDynamicQuery,dynamicQuery,maxRows,preserveNames,dataReturnFormat,nvPairs{:});
复现代码
业务场景代码
dati_Osp = readtable("OSPEDALE1_Reg2.xls"); dati_Osp = renamevars(dati_Osp, 1:width(dati_Osp), ["ANNO", "AZIENDA", "ISTITUTO", "DISCIPLINA_DIMISSIONE", "PROGRESSIVO_REPARTO", "REGIME_DI_RICOVERO", "PROVENIENZA", "DRG", "GIORNATE_DEGENZA", "ACCESSI_IN_DH", "IMPORTO_REGIONALE", "DATA_DIMISSIONE", "COMUNE_DI_RESIDENZA", "ETA", "SESSO", "DIAGNOSI_PRINCIPALE", "DIAGNOSI_CONCOMITANTE1", "DIAGNOSI_CONCOMITANTE2", "DIAGNOSI_CONCOMITANTE3", "DIAGNOSI_CONCOMITANTE4", "INTERVENTO_PRINCIPALE", "INTERVENTO_SECONDARIO1", "INTERVENTO_SECONDARIO2", "INTERVENTO_SECONDARIO3", "INTERVENTO_SECONDARIO4", "MODALITA_DI_ACCESSO", "MODALITA_DI_DIMISSIONE", "TIPO_DI_RICOVERO", "DATA_INGRESSO", "TIPO_PRESCRITTORE", "CODICE_NOSOLOGICO"]); dati_Osp(:, [28, 30]) = []; % 创建/连接数据库 conn_Osp = sqlite("DB_Osp"); sqlwrite(conn_Osp, "dati_Osp", dati_Osp); % 查询首行为NaN的列会报错 fetch(conn_Osp, 'SELECT ACCESSI_IN_DH FROM dati_Osp')
测试用例
conn = sqlite("DBPROVA", 'create'); T = readtable("pratica.txt"); sqlwrite(conn, "pratica", T); fetch(conn,'select * from pratica') close(conn)
pratica.txt内容:
PRATICA GIORNI_DEGENZA COD_REP DRG IMPORTO 2003003986 103 NaN 297 10814 2003004403 78 NaN 462 8490 2003004467 69 7501 012 20941 2003004529 65 7501 012 20173 2003004716 55 3203 014 6289 2003004873 47 NaN 012 15049 2003004980 34 7501 012 10887 2003005005 41 7501 012 13128 2003005050 42 7501 013 13448
问题原因
MatLab通过sqlwrite写入SQLite时,会根据数据表第一行的数据自动推断SQLite列的类型。如果列首是NaN(对应SQLite的NULL值),MatLab无法确定该列的正确数据类型,导致后续fetch查询时解析数据出错。而当列首为有效值时,类型推断正常,后续的NULL(NaN)也能被正确处理。
解决办法
方法1:提前填充NaN值
根据列的业务类型,用合适的默认值替换NaN后再写入数据库:
- 数值型列:可替换为
0、列均值等(根据业务场景选择) - 字符串型列:可替换为空字符串
''
示例代码(处理测试用例):
conn = sqlite("DBPROVA", 'create'); T = readtable("pratica.txt"); % 填充COD_REP列的NaN为0(数值型列) T.COD_REP = fillmissing(T.COD_REP, 'constant', 0); sqlwrite(conn, "pratica", T); fetch(conn,'select * from pratica') close(conn)
方法2:手动指定SQLite表结构
提前创建表并明确指定各列的数据类型,避免自动推断错误:
conn_Osp = sqlite("DB_Osp", "create"); % 手动创建表,指定列类型(示例,需根据实际列调整) sqlquery = "CREATE TABLE dati_Osp (ANNO INTEGER, AZIENDA TEXT, GIORNATE_DEGENZA INTEGER, ACCESSI_IN_DH REAL, IMPORTO_REGIONALE REAL)"; sqlwrite(conn_Osp, sqlquery); % 插入数据 sqlwrite(conn_Osp, "dati_Osp", dati_Osp);
方法3:调整行顺序(临时方案)
将包含有效值的行移至首行,写入数据库后再恢复原顺序:
% 找到列中第一个非NaN的行索引 nonNaNIdx = find(~isnan(dati_Osp.ACCESSI_IN_DH), 1); % 交换首行和非NaN行 tempRow = dati_Osp(1, :); dati_Osp(1, :) = dati_Osp(nonNaNIdx, :); dati_Osp(nonNaNIdx, :) = tempRow; % 写入数据库 sqlwrite(conn_Osp, "dati_Osp", dati_Osp); % 查询完成后若需要,可再将行顺序恢复
内容的提问来源于stack exchange,提问作者BlobFish
相关产品推荐
相关产品推荐

