code review sql – Actualice 12 registros en una tabla de base de datos en menos de 13 consultas

Pregunta:

Tengo una tabla de base de datos en mi aplicación llamada "períodos". La estructura de la tabla es:

  • Año (Número)
  • Mes (Número)
  • Período (Texto)

La columna Año almacena años (por ejemplo, 2016), Mes almacena meses (1-12) y período almacena el período del mes/año, p. ej.; Noviembre de 2016 = 16/11, por lo que el período = 1116.

En la tabla, almacena desde 2016 hasta 2030, por lo que vale 14 años.

En mi código, actualmente tengo la siguiente instrucción Try en el evento de Load mis formularios principales. El objetivo de este código es que el 1 de enero de cada año, la tabla se actualice y establezca la columna Año con 15 años de anticipación, donde año = año actual -1, y luego cree los períodos.

Actualmente usa una actualización para cada registro. ¿Hay alguna manera de reducir el código aquí a menos consultas, pero aún así obtener el efecto deseado?

Por ejemplo, 01/01/2017 establecerá todos los valores de Año en 2031 DONDE Año = 2016, y luego (esta es la parte con la que tuve problemas), establecerá los períodos para que correspondan con el mes y el año de ese registro.

Try
    Dim current As String = Convert.ToString(Date.Today)
    Dim year As String = Convert.ToString(Date.Today.AddYears(-1).Year)
    Dim nextyear As String = Convert.ToString(Date.Today.AddYears(15).Year)
    Dim period As String
    current = current.Substring(0, 5)
    period = nextyear.Substring(2, 2)

      If current = "01/01" Then
         trans = con.BeginTransaction()
         sql = "UPDATE [periods] SET [year] = ? WHERE [year] = ?"

         Dim cmd As New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.Parameters.Add("@y", OleDbType.Integer).Value = year
         cmd.ExecuteNonQuery()

         sql = "UPDATE [periods] SET [period] = ? WHERE [month] = ? AND [year] = ?"

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "01" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 1
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "02" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 2
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "03" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 3
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "04" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 4
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "05" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 5
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "06" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 6
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "07" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 7
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "08" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 8
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "09" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 9
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "10" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 10
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "11" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 11
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         cmd = New OleDbCommand(sql, con, trans)
         cmd.Parameters.Add("@period", OleDbType.VarChar).Value = "12" & period
         cmd.Parameters.Add("@month", OleDbType.Integer).Value = 12
         cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
         cmd.ExecuteNonQuery()

         trans.Commit()

     Else
     End If

 Catch ex As Exception
    trans.Rollback()
     silentErrorLog(ex)

  End Try

Respuesta:

Dim current As String = Convert.ToString(Date.Today) Dim year As String = Convert.ToString(Date.Today.AddYears(-1).Year) Dim nextyear As String = Convert.ToString(Date.Today.AddYears(15).Year) Dim period As String current = current.Substring(0, 5) period = nextyear.Substring(2, 2)

No está claro por qué querrías trabajar con variables de String , dado…

cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear

La base de datos quiere un tipo Integer , por lo que las conversiones Convert.ToString son inútiles en el mejor de los casos, ya que de todos modos va a encajonar el tipo de valor en un Object .

Dim current As Date = Date.Today
Dim year As Integer = Date.Today.AddYears(-1).Year
Dim nextyear As Integer = Date.Today.AddYears(15).Year

No está claro qué está pasando con las siguientes dos instrucciones:

current = current.Substring(0, 5) period = nextyear.Substring(2, 2)

Primero, eso es reasignar current , al que se le ha asignado un valor que nunca se usó. A continuación, estas asignaciones extraen partes específicas de una Date representada como una String , pero no tiene control sobre esa representación: su código podría funcionar en una configuración regional en-US , pero producir resultados sin sentido en una configuración regional fr-FR o en-CA .

No estoy seguro de cuál debería ser el valor de la current después de esa segunda asignación. Suponiendo que digamos 2016/11/02 (¿o sería 11/02/2016 ?), 2016/11/02 los 5 caracteres más a la izquierda serían 2016/ o 11/02 (¿o 02/11 ?), y no tenemos forma de saberlo. con solo leer el código.

Supongo que el period sería 11 (estoy empezando a suponer que su formato de fecha parece 02/11/2016 ), pero, de nuevo, no puedo estar 100% seguro con solo leer el código.

Tampoco está claro por qué el próximo año sería dentro de 15 años: creo que year , nextyear y current podrían usar nombres mejores, más descriptivos y menos engañosos.

Ahora, sin cambiar las consultas SQL reales, su código podría usar un bucle para parametrizar el valor @period :

For month = 1 To 12
    cmd = New OleDbCommand(sql, con, trans)
    cmd.Parameters.Add("@period", OleDbType.VarChar).Value = String.Format("{0:D2}{1}", month, period)
    cmd.Parameters.Add("@month", OleDbType.Integer).Value = month
    cmd.Parameters.Add("@year", OleDbType.Integer).Value = nextyear
    cmd.ExecuteNonQuery()
Next

Ahora, esto limpiará mucho su código, pero aún enviará 12 consultas al servidor de la base de datos.

Parece que se puede derivar la @period parámetro de la @month valor, ¿verdad?

sql = "UPDATE [periods] SET [period] = [month] WHERE [year] = ?"

Por supuesto, eso no funcionará como está. Pero el punto es que querrá modificar la asignación del period para derivar su valor del campo de month en el mismo registro, usando datos que ya están en la base de datos. De esa forma, actualizará todos los registros del year especificado en una sola consulta.


No ha mostrado dónde se inicializa o cierra el objeto con , pero debe estar en un bloque de Using , para que se cierre correctamente y se libere cuando haya terminado con él. Lo mismo OleDbCommand con las instancias de OleDbCommand : la clase implementa la interfaz IDisposable , por lo que debe llamar explícitamente a .Dispose o .Dispose su uso en un ámbito de Using . Hacer eso también haría que su código sea más sensato: al reutilizar el objeto cmd le está dando un nuevo significado cada vez, lo que nunca es una buena idea.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top

web tasarım