与MySql.Data.MySqlClient.MySqlCommand.ExecuteReader

时间:2017-06-08 19:10:11

标签: mysql vb.net

我正在尝试将我的数据从SQLite迁移到MySQL数据库,但这个奇怪的问题一再出现。

我有这个表,与其他表无关:

CREATE TABLE `tableClassesNacionaisH` (
  `id` int(11) DEFAULT NULL,
  `nome` varchar(255) DEFAULT NULL,
  `situacao` varchar(255) DEFAULT NULL,
  `codigoNacional` int(11) DEFAULT NULL,
  `codigoNacionalPai` int(11) DEFAULT NULL,
  `natureza` varchar(255) DEFAULT NULL,
  `dispositivoLegal` varchar(255) DEFAULT NULL,
  `artigo` varchar(255) DEFAULT NULL,
  `sigla` varchar(255) DEFAULT NULL,
  `poloAtivo` varchar(255) DEFAULT NULL,
  `numeracaoPropria` varchar(255) DEFAULT NULL,
  `glossario` text,
  `lft` int(11) DEFAULT NULL,
  `lvl` int(11) DEFAULT NULL,
  `rgt` int(11) DEFAULT NULL,
  `root` int(11) DEFAULT NULL,
  `justEs1Grau` varchar(11) DEFAULT NULL,
  `justEs2Grau` varchar(11) DEFAULT NULL,
  `justEsJuizadoEs` varchar(11) DEFAULT NULL,
  `justEsTurmas` varchar(11) DEFAULT NULL,
  `justEs1GrauMil` varchar(11) DEFAULT NULL,
  `justEs2GrauMil` varchar(11) DEFAULT NULL,
  `justEsJuizadoEsFp` varchar(11) DEFAULT NULL,
  `justTuEsUn` varchar(11) DEFAULT NULL,
  `justFed1Grau` varchar(11) DEFAULT NULL,
  `justFed2Grau` varchar(11) DEFAULT NULL,
  `justFedJuizadoEs` varchar(11) DEFAULT NULL,
  `justFedTurmas` varchar(11) DEFAULT NULL,
  `justFedNacional` varchar(11) DEFAULT NULL,
  `justFedRegional` varchar(11) DEFAULT NULL,
  `justTrab1Grau` varchar(11) DEFAULT NULL,
  `justTrab2Grau` varchar(11) DEFAULT NULL,
  `justTrabTst` varchar(11) DEFAULT NULL,
  `stf` varchar(11) DEFAULT NULL,
  `stj` varchar(11) DEFAULT NULL,
  `cjf` varchar(11) DEFAULT NULL,
  `cnj` varchar(11) DEFAULT NULL,
  `justMilUniao1Grau` varchar(11) DEFAULT NULL,
  `justMilUniaoStm` varchar(11) DEFAULT NULL,
  `justMilEst1Grau` varchar(11) DEFAULT NULL,
  `justMilEstTjm` varchar(11) DEFAULT NULL,
  `justElei1Grau` varchar(11) DEFAULT NULL,
  `justElei2Grau` varchar(11) DEFAULT NULL,
  `justEleiTse` varchar(11) DEFAULT NULL,
  `criadoEm` datetime DEFAULT NULL,
  `atualizadoEm` datetime DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  `poloPassivo` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

为了隔离错误,我编写了这个测试程序:

Private Shared Sub TestSub()
    Dim command_text As String = "SELECT * FROM atena.tableClassesNacionaisH;"
    Dim connection As MySql.Data.MySqlClient.MySqlConnection = AppSet.Atena.Connection
    Dim command As New MySql.Data.MySqlClient.MySqlCommand(command_text, connection)
    Dim table As New DataTable
    Dim dataexception As Exception = Nothing
    Dim rowsinerror As DataRow() = {}
    connection.Open()
    Try
        table.Load(command.ExecuteReader)
    Catch dataexception
    End Try
    connection.Close()
    rowsinerror = table.GetErrors
    If dataexception IsNot Nothing Then
        Debug.Print(dataexception.GetType.ToString)
        Debug.Print(dataexception.Message)
        For Each rowinerror In rowsinerror
            Debug.Print(rowinerror.RowError)
        Next
        Debug.Print(table.Columns("glossario").MaxLength)
    End If
End Sub

按顺序,这些是异常类型,异常消息,第1行错误(英语翻译为我的)和table.Columns("glossario").MaxLength的值:

  

System.Data.ConstraintException

     

激活限制失败。一行或多行包含违反非null,唯一或外键限制的值。

     

列'glossario'超出MaxLength限制。

     

21845

由于我不知道这个数字(21845)是如何被推断的,所以我去了MySQL Workbench并运行了以下查询:

SELECT max(length(glossario)) FROM tableClassesNacionaisH;

结果是34504。

现在问题在于:

*为什么列glossario的MaxLength设置为 21845 ,如果来自该特定查询的实际内容 可以与 34504 <一样长/ strong>和TEXT DataType has maximum length of 65535 characters

我该如何预防/规避这个问题?*

非常感谢。

编辑:一位朋友指出,21845正好是65535的1/3,这让我怀疑这个问题与charset有关。我通过将列的数据类型更改为MEDIUMTEXT来规避它,从而将上限方式提升到16,777,215个字符(或字节?,我不再确定)。但问题仍然存在:MySQL 在TEXT列中存储了一个34504长的字符串而没有截断它。 CLR类型System.String没有21845或65535个字符的这种下限(假设它可能包含大约10亿个字符,但我很少用......)。

1 个答案:

答案 0 :(得分:1)

在您提供的链接中,它明确指出对于TEXT字段,“如果值包含多字节字符,则有效最大长度会减少。

UTF-8是Unicode Charset,是数据库的默认值。它对前128个字符使用1字节表示,与ASCII集匹配,对其余字符使用4字节表示。

这意味着TEXT列可以存储更多或更少的字符,具体取决于字符是否为ASCII。

现在,当MySQL驱动程序无法正确处理此问题时,您的问题就出现了,将假设所有UTF-8字符都是4字节宽,并将列长度除以4个字节,将其作为实际字段长度传递给DataTable。这意味着在技术上可以在数据库中包含一些不适合DataTable的文本,就像你的情况一样。

您的问题的解决方案(或本例中的解决方法)正是您现在所做的,即将列更改为可包含更多字符的类型,如MEDIUMTEXT或LONGTEXT。

我的猜测是这个决定是为了简化MySQL驱动程序的实现,但我会考虑向Oracle提交错误报告。