none
Dejar como nulo un campo de SQL Server RRS feed

  • Pregunta

  • Buen Día estimados, me estoy topando con un problema en mi proyecto de Visual Basic

    Tengo un DataGridView que es editable incrustado en un Form , este control contiene 12 columnas en total de las cuales 4 de ellas pueden dejarse en blanco, hasta ahi todo bien . Pero lo que ocurre es que a la tabla se insertan los registros en Blanco, no como NULL y deseo que estos aparezcan como null.

     USER_ORDER_QTY = DataGridView1.Rows(ii).Cells(0).Value
                            PURCHASE_UM = DataGridView1.Rows(ii).Cells(1).Value
                            cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            If GL_EXPENSE_ACCT_ID Is "" Then
                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", DBNull.Value.ToString)
                            Else
                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            End If

    Estaría agradecido por su ayuda

    sábado, 1 de junio de 2019 18:22

Respuestas

  • Vale, ya se ve lo que pasa: En la sentencia SQL no estás usando el parámetro. Solamente estás concatenando las variables dentro del texto de la sentencia. Por lo tanto, no sirve para nada asignar el DBNull al parámetro, puesto que el parámetro no se usa.

    Por cierto, una vez que parametrices la sentencia, me acabo de dar cuenta de otro error: Al construir el parámetro estás usando "AddWithValue". Esto solo vale cuando se añade de verdad un valor para que el AddWithValue pueda inferir el tipo a partir del valor. Pero si le pasas DBNull no se puede inferir el tipo. En estos casos hay que usar la sintaxis larga con el "Add" en lugar del "AddWithValue" y poner el SqlDbType correcto. Pero no sirve de nada corregir esto mientras sigas sin usar el parámetro. Tienes que incrustarlo en la sentencia en lugar de concatenar la variable.

    Es decir, en lugar de poner

    '" & GL_EXPENSE_ACCT_ID & "'

    tienes que poner

    @GL_EXPENSE_ACCT_ID

    para que te tome ese parámetro.

    • Propuesto como respuesta Carlos_Ruiz_M martes, 4 de junio de 2019 14:04
    • Marcado como respuesta Luis Alvarenga martes, 4 de junio de 2019 15:15
    martes, 4 de junio de 2019 6:21

Todas las respuestas

  • Cámbialo así:

                           If String.IsNullOrWhitespace(GL_EXPENSE_ACCT_ID) Then
                                 cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", DBNull.Value)
                             Else
                                 cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                             End If

    Observa que no puedes usar is "" para ver si está vacío. Hay varias formas de hacer la comparación, pero el operador "is" no es una de ellas.

    Y otra cosa absolutamente crítica es que no puedes poner .ToString detrás del DBNull.Value. Es forzoso pasar el Value, si pasas Value.ToString te grabará en el registro la cadena de texto "System.DBNull.Value" en lugar de grabar un NULL.

    • Propuesto como respuesta Carlos_Ruiz_M lunes, 3 de junio de 2019 14:19
    sábado, 1 de junio de 2019 18:57
  • He aplicado el código tal cual lo has propuesto mi estimado, pero aun en el campo de la base de Datos el registro se gurada en blanco.

    Nota: En visual Basic 

    String.IsNullOrWhitespace no me aparece

    Solo me aparece : String.IsNullOrEmpty

     cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            If String.IsNullOrEmpty(GL_EXPENSE_ACCT_ID) Then

                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", DBNull.Value)
                              
                            Else
                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            End If

    lunes, 3 de junio de 2019 16:24
  • String.IsNullOrWhitespace no me aparece
    Solo me aparece : String.IsNullOrEmpty

    Eso significa que estás usando una versión super-antigua del Framework. El IsNullOrWhitespace lo añadieron en el 4.0. No importa, con String.IsNullOrEmpty también te funcionará, a condición de que efectivamente el campo esté vacío (y no relleno con espacios en blanco, o con un retorno de carro o algo similar).

    Por lo demás el parámetro tal como lo tienes (con DBNull.Value) es correcto. Si no funciona, tiene que haber algún error en algún otro sitio que no vemos en este fragmento de código, posiblemente en la propia sentencia de inserción, aunque también podría ser un trigger en la base de datos o alguna otra circunstancia que no se aprecia en el código que vemos. Recomiendo usar el debugger y seguir la ejecución paso-a-paso hasta alcanzar el punto en el que se realiza la inserción, y ahi examinar qué es lo que hay cargado en el command (CommandText y parámetros), a ver si todo es correcto. Si lo es, entonces usar el SQL Profiler para capturar la sentencia y ver qué es lo que le está llegando realmente al servidor de base de datos.

    • Propuesto como respuesta Carlos_Ruiz_M martes, 4 de junio de 2019 14:04
    lunes, 3 de junio de 2019 17:57
  • En efecto el campo donde el usuario hace uso del ControlDGV esta vacio osea que lo deja  "En blanco"y el programa lo deja seguir porque durtante el proceso de gestión el usuario no esta obligado a ingresar ese campo lo agregará solo se el lo sabe.

    Aun asi no se porque no funciona me deja siempre el espacio en Blanco en la tabla

    Aquí te muestro un poco más del código.

    Todo lo estoy haciendo dentro de un For pues el me ayuda a recorrer el control y guardar los datos en al tabla, por el momento todos los datos se guardan correctamente.

             '*****     INSERT LINEAS DE DETALLE A LA TABLA PURC_REQ_LINE DESDE DGV1     *****
                        Dim connectionString9 As String = "Server=xxxx;Database=xxxx;User Id=sa;Password=xxx"
                        Dim sqlCnn9 As SqlConnection = New SqlConnection(connectionString9)
                        Dim sqlCmd9 As SqlCommand
                        Dim sql9 As String 

     '*********** USO DE FOR ***************

    For ii = 0 To Me.DataGridView1.Rows.Count - 1
                            Dim USER_ORDER_QTY As Decimal
                            Dim PURCHASE_UM, GL_EXPENSE_ACCT_ID, USER_ARTICULO, PART_ID, DESCRIPTION, DESIRED_RECV_DATE, DESTINO2 As String
                            Dim VAT_CODE As String
                            Dim UNIT_PRICE, VAT_AMOUNT As Decimal
                            Dim TOTAL_GENERAL As Double
                            Dim PRODUCT_CODE As Integer = Nothing
                            Dim COMMODITY_CODE As Integer = Nothing
                            Dim TOTAL_AMT_RECVD As Integer = Nothing
                            Dim VAT_RCV_AMOUNT As Integer = Nothing
                            USER_ORDER_QTY = DataGridView1.Rows(ii).Cells(0).Value
                            PURCHASE_UM = DataGridView1.Rows(ii).Cells(1).Value
                            cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            If String.IsNullOrEmpty(GL_EXPENSE_ACCT_ID) Then

                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", DBNull.Value)
                                MsgBox("IF")
                            Else
                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            End If
                            GL_EXPENSE_ACCT_ID = Me.DataGridView1.Rows(ii).Cells(2).Value
                            USER_ARTICULO = IIf(DataGridView1.Rows(ii).Cells(3).Value Is System.DBNull.Value, Nothing, DataGridView1.Rows(ii).Cells(3).Value)
                            PART_ID = DataGridView1.Rows(ii).Cells(4).Value
                            DESCRIPTION = DataGridView1.Rows(ii).Cells(5).Value
                            DESIRED_RECV_DATE = Format((DataGridView1.Rows(ii).Cells(6).Value), "yyyy-MM-dd")
                            UNIT_PRICE = IIf(DataGridView1.Rows(ii).Cells(7).Value Is System.DBNull.Value, vbNull, DataGridView1.Rows(ii).Cells(7).Value)
                            VAT_CODE = IIf(DataGridView1.Rows(ii).Cells(8).Value Is System.DBNull.Value, vbNullString, DataGridView1.Rows(ii).Cells(8).Value)
                            TOTAL_AMT_ORDERED = IIf(DataGridView1.Rows(ii).Cells(9).Value Is "", 0, DataGridView1.Item(9, ii).Value)
                            VAT_AMOUNT = IIf(DataGridView1.Rows(ii).Cells(10).Value Is "", 0, DataGridView1.Rows(ii).Cells(10).Value)
                            TOTAL_GENERAL = IIf(DataGridView1.Rows(ii).Cells(11).Value Is "", 0, DataGridView1.Rows(ii).Cells(11).Value)
                            DESTINO2 = DataGridView1.Rows(ii).Cells(12).Value

     ************Insert****************

     sql9 = "INSERT INTO PURC_REQ_LINE (PURC_REQ_ID, LINE_NO, PART_ID, USER_ORDER_QTY, ORDER_QTY, PURCHASE_UM, UNIT_PRICE, TRADE_DISC_PERCENT, FIXED_CHARGE,EST_FREIGHT, GL_EXPENSE_ACCT_ID, PRODUCT_CODE, COMMODITY_CODE, DESIRED_RECV_DATE, LINE_STATUS, TOTAL_AMT_RECVD, TOTAL_AMT_ORDERED, VAT_CODE, WAREHOUSE_ID, ALLOCATED_QTY, FULFILLED_QTY, USER_1, USER_2, VAT_AMOUNT, VAT_RCV_AMOUNT, STATUS_EFF_DATE) VALUES('" & numero_rq & "', (" & ii & " + 1), '" & PART_ID & "' ,'" & USER_ORDER_QTY & "' , '" & USER_ORDER_QTY & "', '" & PURCHASE_UM & "', '" & UNIT_PRICE & "', 0, 0, 0, '" & GL_EXPENSE_ACCT_ID & "', '" & PRODUCT_CODE & "',  '" & COMMODITY_CODE & "' , '" & DESIRED_RECV_DATE & "','T', '" & TOTAL_AMT_RECVD & "', '" & TOTAL_AMT_ORDERED & "', '" & VAT_CODE & "' , '" & almacen & "' , 0 ,0 ,'" & USER_ARTICULO & "', '" & DESTINO2 & "', '" & VAT_AMOUNT & "', '" & VAT_RCV_AMOUNT & "', GETDATE() )"

                            Try
                                sqlCnn9.Open()
                                sqlCmd9 = New SqlCommand(sql9, sqlCnn9)
                                Dim sqlReader9 As SqlDataReader = sqlCmd9.ExecuteReader()
                                sqlReader9.Close()
                                sqlCmd9.Dispose()
                                sqlCnn9.Close()
                            Catch ex8 As Exception
                                sqlCnn9.Close()
                                MsgBox("Ingreso no fue realizado. Error 1: " & ex8.Message)
                            End Try

    Next

    lunes, 3 de junio de 2019 18:13
  • Vale, ya se ve lo que pasa: En la sentencia SQL no estás usando el parámetro. Solamente estás concatenando las variables dentro del texto de la sentencia. Por lo tanto, no sirve para nada asignar el DBNull al parámetro, puesto que el parámetro no se usa.

    Por cierto, una vez que parametrices la sentencia, me acabo de dar cuenta de otro error: Al construir el parámetro estás usando "AddWithValue". Esto solo vale cuando se añade de verdad un valor para que el AddWithValue pueda inferir el tipo a partir del valor. Pero si le pasas DBNull no se puede inferir el tipo. En estos casos hay que usar la sintaxis larga con el "Add" en lugar del "AddWithValue" y poner el SqlDbType correcto. Pero no sirve de nada corregir esto mientras sigas sin usar el parámetro. Tienes que incrustarlo en la sentencia en lugar de concatenar la variable.

    Es decir, en lugar de poner

    '" & GL_EXPENSE_ACCT_ID & "'

    tienes que poner

    @GL_EXPENSE_ACCT_ID

    para que te tome ese parámetro.

    • Propuesto como respuesta Carlos_Ruiz_M martes, 4 de junio de 2019 14:04
    • Marcado como respuesta Luis Alvarenga martes, 4 de junio de 2019 15:15
    martes, 4 de junio de 2019 6:21
  • Entiendo estimado , pero cual parámetro debo poner, pues no se cual poner.

    Cuando lo ejecuto de esta forma me sale error , error de objeto o instancia no reconocido

     cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            If String.IsNullOrEmpty(GL_EXPENSE_ACCT_ID) Then

                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", DBNull.Value)

                            Else
                                cmd7.Parameters.AddWithValue("@GL_EXPENSE_ACCT_ID", GL_EXPENSE_ACCT_ID)
                            End If

    Ya cambie la sentencia SQL y lo deje tal cual con el parametro @variable sin comillas ni asperson

    martes, 4 de junio de 2019 15:22
  • Pero ¿cómo ha quedado? Ponnos aquí cómo es la parte de código donde ejecutas la sentencia y cómo es la parte donde metes el parámetro. La última que pusiste a simple vista parece igual que la penúltima. Señala por favor qué es lo que has cambiado. Y cuando dé un error, indica siempre la línea exacta en la que ocurre, además del texto exacto del error.
    martes, 4 de junio de 2019 15:58
  • Que tal estimado te comento que ya me funcionó lo que quería lograr, tuve que extender una condición aun más específica del IF 

    * Use iif() antes del control DataGridView

    * Le puse is Dbnull.Value,Nothing para asegurar que lo seteara como NULL en la base de datos 

    * Con el resto de campos use, vbNull y me funcionó perfecatamente con ambos ahora ya deja como NULL en la bas de datos los campos que el usuario no ingresa.

    GL_EXPENSE_ACCT_ID = IIf(Me.DataGridView1.Rows(ii).Cells(2).Value Is DBNull.Value, Nothing,  Me.DataGridView1.Rows(ii).Cells(2).Value)

     USER_ARTICULO = IIf(DataGridView1.Rows(ii).Cells(3).Value Is "", vbNull, DataGridView1.Rows(ii).Cells(3).Value)

    Muchas gracias por la ayuda

    martes, 4 de junio de 2019 22:37