Pregunta

Soy desarrollador de Java. Tengo un programa antiguo en Delphi. En la versión anterior trabajan mdb. Lo arreglé para la conexión con SQL Server. Todas las consultas SQL se implementan con TAdoQuery.

qryTemp.SQL.Text:='select  sum(iif(ComeSumm>0,comesumm,0)),sum(iif(lostSumm>0,lostsumm,0)) from cash '+
   'where (IdCashClause is null or idcashclause<>8) '+
  ' and cashNum='+IntToStr(i)+
  ' and CashType=0'+
  ' and format(PayDate,"dd/mm/yyyy")=format('''+DateToStr(Date)+''',"dd/mm/yyyy") ';

El programa lanza una excepción:

Nombre de la columna no válido 'DD/MM/YYYY'.

He arreglado otra consulta para comparar:

 qryTemp.SQL.Text:=' select top 1 iif(ComeSumm>0,comesumm,0) from cash '
                     +' where idCashReason=1 and idCashClause=8 and cashNum='+IntToStr(i)
                     +' and PayDate<:D'
                     +' order by payDate desc';
qryTemp.Parameters.ParamByName('D').Value:=DateTimeToStr(Date);

¿Puedo arreglar rápidamente todas las consultas para trabajar con SQL Server sin reescribir todo el proyecto?

¿Fue útil?

Solución

Asumiendo PayDate Se define como date/datetime En MSSQL puede usar parámetros de la siguiente manera:

qryTemp.SQL.Text:=' select top 1 iif(ComeSumm>0,comesumm,0) from cash '
                     +' where idCashReason=1 and idCashClause=8 and cashNum='+IntToStr(i)
                     +' and PayDate<:D'
                     +' order by payDate desc';
qryTemp.Parameters.ParamByName('D').Value := Date;
qryTemp.Parameters.ParamByName('D').DataType := ftDateTime;

También cambiaría cashNum a parámetro es decir:

...
+' where idCashReason=1 and idCashClause=8 and cashNum=:cashNum'+
...
qryTemp.Parameters.ParamByName('cashNum').Value := i;

Siempre prefiera usar tipos de datos compatibles con sus parámetros, en lugar de formatear y usar cadenas. SQL no necesita adivinar sus tipos de datos si puede definirlos explícitamente.

Nota: IIF se introdujo en SQL Server 2012. Para el uso de la versión anterior CASO expresión.


En las versiones de Delphi no unicode más antiguas, los parámetros tienen problemas con Unicode.
Así que si usted no Use parámetros que pueda usar lo siguiente:

function DateTimeToSqlDateTime(const DT: TDateTime): WideString;
begin
  Result := FormatDateTime('yyyy-MM-dd', DT) + ' ' + FormatDateTime('hh:mm:ss', DT);
end;

function SqlDateTimeStr(const DT: TDateTime; const Is_MSSQL: Boolean): WideString;
var
  S: WideString;
begin
  S := DateTimeToSqlDateTime(DT);
  if Is_MSSQL then
    Result := Format('CONVERT(DATETIME, ''%s'', 102)', [S]) 
  else
    Result := Format('#%s#', [S]); // MS-ACCESS
end;

Y su consulta se verá de la siguiente manera:

...
+' and PayDate<' + SqlDateTimeStr(Date, True)
...

Otros consejos

Es muy probable que el PayDate La columna se declara como DATE en el cash mesa. Teniendo en cuenta que su parámetro debería ser un TDateTime Y no un string, como esto:

qryTemp.SQL.Text:=' select top 1 iif(ComeSumm>0,comesumm,0) from cash '
                     +' where idCashReason=:cashReason and idCashClause=8 and cashNum='+IntToStr(i)
                     +' and PayDate<:D'
                     +' order by payDate desc';
qryTemp.Parameters.ParamByName('D').Value := Date;

Reemplazé solo uno de los parámetros, pero debe considerar reemplazarlos a todos, ya que esto mejorará el rendimiento del servidor al habilitar su caché de oraciones.

Volviendo a su pregunta original, supongo que la única forma de refactorizar toda la aplicación sería tener un programa de refactorización que pueda analizar su código, encontrar esas situaciones y seguir un patrón para reemplazar una pieza de código por otro.

No conozco ninguna herramienta que pueda hacer eso ahora.

Tal vez usar Find/Reemplazar que admite expresiones regulares puede ayudarlo, pero ciertamente no arreglará los casos en un solo pase. Tendría que ejecutar una serie de fases de reemplazo para transformar su código de lo que es a lo que desea que sea.

DatoToSTR utiliza información de localización contenida en variables globales para formatear la cadena de fecha. quizá este es el problema.

Puedes probar FormatDateTime:

qryTemp.SQL.Text:='select  sum(iif(ComeSumm>0,comesumm,0)),sum(iif(lostSumm>0,lostsumm,0)) from cash '+
   'where (IdCashClause is null or idcashclause<>8) '+
  ' and cashNum='+IntToStr(i)+
  ' and CashType=0'+
  ' and format(PayDate,"dd/MM/yyyy")='''+FormatDateTime('dd/mm/yyyy',Date)+'''';
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top