【问题标题】:Trouble writing to SQL无法写入 SQL
【发布时间】:2015-04-17 12:28:34
【问题描述】:

我已经在 VB.Net 中编写了几个月,并且在我的代码中多次成功使用 SQL 命令,但是在写入数据库中的一个特定表时遇到了麻烦。我相信问题在于我有一个我正在尝试写入的数字列(我得出这个结论是因为它是我唯一不经常使用的列)并且我的代码不断出现异常:附加信息:SqlCommand.Prepare 方法要求所有可变长度参数具有显式设置的非零大小。代码:

    Dim cn As System.Data.SqlClient.SqlConnection
    Dim command As System.Data.SqlClient.SqlCommand

    Dim VL1 As System.Data.SqlClient.SqlParameter
    Dim VL2 As System.Data.SqlClient.SqlParameter
    Dim VL3 As System.Data.SqlClient.SqlParameter
    Dim VL4 As System.Data.SqlClient.SqlParameter

    Dim commandText As String

    cn = New System.Data.SqlClient.SqlConnection(ConnectStr)
    cn.Open()

    commandText = "INSERT INTO [dbo].[HourMeterLog]" _
                    + "([MachineName],[TotalHours],[HLRD],[DateTime])" _
                    + "VALUES (@VL1,@VL2,@VL3,@VL4)"

    command = New System.Data.SqlClient.SqlCommand(commandText, cn)

    VL1 = command.Parameters.Add("@VL1", System.Data.SqlDbType.NVarChar, 25)
    VL2 = command.Parameters.Add("@VL2", System.Data.SqlDbType.Float)
    VL3 = command.Parameters.Add("@VL3", System.Data.SqlDbType.Int, 10)
    VL4 = command.Parameters.Add("@VL4", System.Data.SqlDbType.DateTime2, 0)

    command.Prepare()

    VL1.Value = "MachineName"
    VL2.Value = 0
    VL3.Value = 735562
    VL4.Value = Now()

    command.ExecuteNonQuery()

    cn.Close()

我知道我的代码可以连接,因为我至少有 15 个使用这种格式的其他查询。我宁愿不使用浮点数写入数字字段,但我第一次启动此代码时它就工作了(从那时起就没有一次)。

【问题讨论】:

  • 对于那些想知道我有为整个班级声明的连接字符串的人,因为我只写到这个程序上的一个服务器。它变暗:Server=Server;uid=User;pwd=Password;database=Example
  • 我已经有一段时间没有做过很多 SQL 了,但我认为您不需要提供 Int 或 DateTime2 参数的长度。试着把长度拿出来看看它是否有效?
  • 首先 - 我建议您在 using 语句中确定您的连接范围等。第二 - 尝试只为参数做 AddWithValue (msdn.microsoft.com/en-us/library/…) 并放弃准备(至少现在为了保持简单)。如果链接中的代码示例有效,您就知道您的连接工作。最后添加一个 try/catch 以便在失败时轻松查看异常。
  • 我尝试了 AddWithValue 方法,它导致了同样的错误。
  • 您是否尝试过在command.Parameters.Add() 命令中不提供大小?

标签: sql-server vb.net


【解决方案1】:

根据MSDNDateTime2 的最大字符长度为 27。所以我将DateTime2 的长度设置为 27,并且工作正常。

 VL4 = command.Parameters.Add("@VL4", System.Data.SqlDbType.DateTime2, 27)

我的工作代码是,

    Dim cn As System.Data.SqlClient.SqlConnection
    Dim command As System.Data.SqlClient.SqlCommand

    Dim VL1 As System.Data.SqlClient.SqlParameter
    Dim VL2 As System.Data.SqlClient.SqlParameter
    Dim VL3 As System.Data.SqlClient.SqlParameter
    Dim VL4 As System.Data.SqlClient.SqlParameter

    Dim commandText As String

    cn = New System.Data.SqlClient.SqlConnection(connectionString)
    cn.Open()

    commandText = "INSERT INTO [dbo].[HourMeterLog]" _
                    + "([MachineName],[TotalHours],[HLRD],[DateTime])" _
                    + "VALUES (@VL1,@VL2,@VL3,@VL4)"

    command = New System.Data.SqlClient.SqlCommand(commandText, cn)

    VL1 = command.Parameters.Add("@VL1", System.Data.SqlDbType.NVarChar, 25)
    VL2 = command.Parameters.Add("@VL2", System.Data.SqlDbType.Float)
    VL3 = command.Parameters.Add("@VL3", System.Data.SqlDbType.Int, 10)
    VL4 = command.Parameters.Add("@VL4", System.Data.SqlDbType.DateTime2, 27)

    command.Prepare()

    VL1.Value = "MachineName"
    VL2.Value = 0
    VL3.Value = 735562
    VL4.Value = Now()

    command.ExecuteNonQuery()

    cn.Close()

【讨论】:

  • 我会试试看它是否会写入我的表。希望它能起作用,因为我更喜欢这种格式来写入 SQL 而不是 AddWithValue 方法。
  • 这对我也有用,谢谢你是我的英雄。我可以保持我喜欢的格式。
【解决方案2】:

好吧,我想我在尝试时写错了 AddWithValue 方法。我得到了要写的命令:

Dim cn As System.Data.SqlClient.SqlConnection
Dim command As System.Data.SqlClient.SqlCommand

Dim VL1 As System.Data.SqlClient.SqlParameter
Dim VL2 As System.Data.SqlClient.SqlParameter
Dim VL3 As System.Data.SqlClient.SqlParameter
Dim VL4 As System.Data.SqlClient.SqlParameter

Dim commandText As String

cn = New System.Data.SqlClient.SqlConnection(ConnectStr)
cn.Open()

commandText = "INSERT INTO [dbo].[HourMeterLog]" _
                + "([MachineName],[TotalHours],[HLRD],[DateTime])" _
                + "VALUES (@VL1,@VL2,@VL3,@VL4)"

command = New System.Data.SqlClient.SqlCommand(commandText, cn)

VL1 = command.Parameters.AddWithValue("@VL1", "MachineName")
VL2 = command.Parameters.AddWithValue("@VL2", 0)
VL3 = command.Parameters.AddWithValue("@VL3", 735562)
VL4 = command.Parameters.AddWithValue("@VL4", Now())

'VL1 = command.Parameters.Add("@VL1", System.Data.SqlDbType.NVarChar, 25)
'VL2 = command.Parameters.Add("@VL2", System.Data.SqlDbType.Float)
'VL3 = command.Parameters.Add("@VL3", System.Data.SqlDbType.Int)
'VL4 = command.Parameters.Add("@VL4", System.Data.SqlDbType.DateTime2)

'command.Prepare()

'VL1.Value = "MachineName"
'VL2.Value = 0
'VL3.Value = 735562
'VL4.Value = Now()

command.ExecuteNonQuery()

cn.Close()

我真的更喜欢使用我以前使用过的格式,但我很高兴我至少现在正在写作。谢谢你们的帮助。如果有人对如何改进我的原始格式以使其正确书写有任何想法,请告诉我。对于那些想要在表格上获得一些信息的人,我也在写 Float 写入的字段是 Numeric(18,1) 字段。除了该列之外,其他列可以从代码中推断出来。

【讨论】:

    【解决方案3】:

    这里是一个简短的例子,SqlParameter 的 'Size' 参数有什么影响。

    示例表是

    CREATE TABLE [dbo].[DateTimeTest](
        [CreatedAt] [datetime2](7) NOT NULL,
        [SizeValue] [int] NOT NULL
    ) ON [PRIMARY]
    

    C# 中的示例代码是

        string connectionString = "Data Source=.;Integrated Security=SSPI;Initial Catalog=Sandbox";
    
    using (SqlConnection connection = new(connectionString))
    {
        connection.Open();
        
        string commandText = @"
                INSERT INTO [dbo].[DateTimeTest]
                           ([CreatedAt]
                           ,[SizeValue])
                     VALUES
                           (@CreatedAt
                           ,@SizeValue);
                ";
    
        DateTime timestamp = DateTime.Now;
    
        for (int i = 1; i < 28; i++)
        {
            SqlCommand command = new SqlCommand(commandText, connection);
    
            SqlParameter createdAtParam = new SqlParameter("@CreatedAt", SqlDbType.DateTime2, i); // i = 0 will raise an exception on call to command.Prepare()
            command.Parameters.Add(createdAtParam);
            createdAtParam.Value = timestamp;
    
            SqlParameter sizeValueParam = new SqlParameter("@SizeValue", SqlDbType.Int);
            command.Parameters.Add(sizeValueParam);
            sizeValueParam.Value = i;
    
            command.Prepare();
            command.ExecuteNonQuery();
        }
    }
    

    如您所见,'Size' 的值对插入的 DateTime 值的精度没有影响。

    SqlParameter createdAtParam = new SqlParameter("@CreatedAt", SqlDbType.DateTime2, 0);
    

    SqlParameter createdAtParam = new SqlParameter("@CreatedAt", SqlDbType.DateTime2);
    

    将在调用时引发异常

    command.Prepare();
    

    【讨论】:

    • 所以 .... size=0 你会得到一个错误。那是OP的问题。 “SqlCommand.Prepare 方法要求所有可变长度参数具有显式设置的非零大小”问题不在于字段精度。您是在添加信息,而不是在解决问题。
    【解决方案4】:

    对于错误消息,对您的表一无所知...

    “SqlCommand.Prepare 方法要求所有可变长度参数具有显式设置的非零大小

    来自 MSDN (https://msdn.microsoft.com/en-us/library/40959t6x(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1)

    'Declaration
    Public Function Add ( _
    parameterName As String, _
    sqlDbType As SqlDbType, _
    size As Integer _
    ) As SqlParameter
    

    也许你的问题来自:

    VL4 = command.Parameters.Add("@VL4", System.Data.SqlDbType.DateTime2, 0)
    

    改成

    VL4 = command.Parameters.Add("@VL4", System.Data.SqlDbType.DateTime2)
    

    【讨论】:

    • 我使用了 try catch 并在消息框中显示异常,它提供的数据指向 VL2 = command.Parameters.Add("@VL2", System.Data.SqlDbType.浮动)
    • 操作!在 msdn 示例中,对于没有 size 参数的方法,size 是稍后分配的。很高兴看到您的问题已解决。问候!
    • System.Data.SqlDbType.DateTime2 确实需要 'Size' 值为 1 - 我的示例如下。
    猜你喜欢
    • 2017-01-09
    • 1970-01-01
    • 2020-12-16
    • 2013-10-10
    • 2017-09-06
    • 2013-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多