首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

,有没有将SQL Server的SQL翻译为Oracle的第三方组件

2012-12-22 
紧急求助,有没有将SQL Server的SQL翻译为Oracle的第三方组件?最近接到一个项目,不是很大,但客户要求数据库

紧急求助,有没有将SQL Server的SQL翻译为Oracle的第三方组件?
最近接到一个项目,不是很大,但客户要求数据库用oracle,而我们的系统是在sql server下做的,我们的系统在程序中嵌入了大量的SQL语句,如果全部手动翻译几乎是不可能的,我们的系统基于delphi的midas三层架构,幸好系统设计时将所有的SQL(包括客户端和中间层)都是通过中间层一个统一的接口来执行的,我想,如果在这个接口中将需要执行的SQL进行语法转换,就可以直接支持oracle了,但这种转换也算是一种高技术含量的活,想请教一下各位见多识广的大虾,有没有现成的第三方组件可以完成这个工作?例如,我传一个SQL Server规范的SQL给组件,组件返回一个支持Oracle规范的SQL给我就行了。感谢~!
[最优解释]
异想天开.
[其他解释]
首先你的SQL语句是用SQL99的规范写的吗?
如果你的SQLSERVER上面不运行SP,只是直接SQL语句写的话,那你比较幸运,ORACLE和SQLSERVER在SQL语句上面的差异主要在函数上,比如日期函数之类的。这样改起来比较简单。
如果你在SQLSERVER上布置了大量的SP,那你只能慢慢改了,ORACLE和SQLSERVER的SP还是区别很大的。

[其他解释]
找到以后给我传一个 谢谢
[其他解释]
这个不大现实,有些东西还是得手工做一下。。。。。

[其他解释]
可以去oracle版块问问,或者直接咨询oracle的技术支持。。。
[其他解释]
呵,若是SP,改动反而更容易。。。。若是在客户端,那就只有到处搜索喽

[其他解释]

引用:
异想天开.


我觉得并非异想天开,事实上我已经找到这个工具(sqlways),里面有提供这样的功能,但可惜不是组件。
[其他解释]
引用:
首先你的SQL语句是用SQL99的规范写的吗?
如果你的SQLSERVER上面不运行SP,只是直接SQL语句写的话,那你比较幸运,ORACLE和SQLSERVER在SQL语句上面的差异主要在函数上,比如日期函数之类的。这样改起来比较简单。
如果你在SQLSERVER上布置了大量的SP,那你只能慢慢改了,ORACLE和SQLSERVER的SP还是区别很大的。


SP很少
[其他解释]
引用:
呵,若是SP,改动反而更容易。。。。若是在客户端,那就只有到处搜索喽


所有SQL的执行,都是通过AppServer里一个的函数来完成的,也许不需要这样做~
[其他解释]
挺麻烦的。
[其他解释]
花了两天时间,基本上搞定(还有待完善,但最核心的已经可以,包括函数提取和替换算法已经搞定):

unit SqlConvertToOracle;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

Type

   TSqlFuncInfo = record
     Name: string;
     ArgCount: integer;
     Args: array [0..10] of string[100];
   end;

//最终需要调用的函数
function ConvertSQLToOracle(ASQL: string): string;

//从SQL中提取函数信息
function GetFirstFuncInfo(ASQL, AFuncName: string; var ABegin, AEnd: integer; var AFunInfo: TSqlFuncInfo): boolean;

//将原来的函数替换成新的函数(包括参数)
function ReplaceFunctionByNew(ASQL: string; ABegin, AEnd: integer; AFuncInf, ANewFuncInf: TSqlFuncInfo): string;

//转换SQl Server中以 = 表示的列别名,例如: Abc = Field1 转换为 Field1 Abc
function ConvertFieldAlias(ASQL: string): string;

implementation

function ReplaceCommons(ASQL: string): string;
begin
  Result := StringReplace(ASQL, ' #', ' T_', [rfReplaceAll]);  //临时表的名称
  Result := StringReplace(Result, ' as ', ' ', [rfReplaceAll]); //别名去掉as


end;

function ConvertTopNWord(ASQL: string): string;
var
  n, n2, i, topN: integer;
  sTmp: string;
begin
  Result := ASQL;
  n := pos(' top ', Result);
  if n <= 0 then
    Exit;
  i := n + 4;
  sTmp := '';
  while Result[i] = ' ' do
    inc(i);
  while not (Result[i] in [' ', '(']) do
  begin
    sTmp := sTmp + Result[i];
    inc(i);
  end;
  n2 := i - 1;
  if sTmp <> '' then
    topN := strtoint(sTmp)
  else
    topN := -1;
  Delete(Result, n + 1, n2 - n); //删除原来的 top N,只留一个空格
  n := pos(' where ', Result);
  if n > 0 then
    Result := Copy(Result, 1, n - 1) + ' where (' + copy(Result, n +6, length(Result)) + ') And ROWNUM <= ' + inttostr(TopN)
  else
    Result := Result + ' Where ROWNUM <= ' + inttostr(TopN);
end;

//转换SQl Server中以 = 表示的列别名,例如: Abc = Field1 转换为 Field1 Abc
function ConvertFieldAlias(ASQL: string): string;
var
  st, n, k, j, p1, p2, p3, p4, p5: integer;
  sTmp, sPttr, Word1, Word2, Word3, Word4, Word5: string;
  b: boolean;

  function _Check: boolean;
  begin
    Result := false;
    if (pos('select', Word1) > 0) or (pos('select', Word3) > 0) then
      Result := true
    else
    begin
      k := p3;
      while k <= p4 do
      begin
        if ASQL[k] = ',' then
        begin
          Result := true;
          Exit;
        end;
        Inc(k);
      end;

    end;
  end;
  
begin
  Result := '';
  sTmp := '';
  //最近5个单词
  Word1 := '';
  Word2 := '';
  Word3 := '';
  Word4 := '';
  Word5 := '';
  n := 1;
  //最近5个单词的尾部位置
  p1 := 1;
  p2 := 1;
  p3 := 1;
  p4 := 1;
  p5 := 1;
  b := false;
  st := 0;


  //扫描
  while n <= Length(ASQL) do
  begin
    if ASQL[n] = '(' then
      Inc(st)
    else
    if ASQL[n] = ')' then
      Dec(st);

    if (ASQL[n] in [' ', '=', #13, #10, ',']) and (st = 0) then
    begin
      Word1 := Word2;
      Word2 := Word3;
      Word3 := Word4;
      Word4 := Word5;
      Word5 := sTmp;
      sTmp := '';
      p1 := p2;
      p2 := p3;
      p3 := p4;
      p4 := p5;
      p5 := n;

      while (n <= Length(ASQL)) and (ASQL[n] in [' ', ',', #13, #10]) do
      begin
       /// Result := Result + ASQL[n];
        Inc(n);
      end;

      if b then
      begin
        b := false;
        if _Check then
        begin
          sPttr := Word5 + ' ' + Word4;
          j := (P5-1) - (P4 - Length(Word4)) + 1; //原串的长度
          while Length(sPttr) < j do
            sPttr := sPttr +' ';
          j := 1;
          for k := (P4 - Length(Word4)) to P5 - 1 do
          begin
            ASQL[k] := sPttr[j];
            Inc(j);
          end;
         // Result := Result + Word5 + ' ' + Word4;
        end;
      end;
      if ASQL[n]  = '=' then
        b := true;

      while (n <= Length(ASQL)) and (ASQL[n] in [' ', '=', ',', #13, #10]) do
      begin
      //  Result := Result + ASQL[n];
        Inc(n);
      end;
              


    end;
    
   // Result := Result + ASQL[n];
    sTmp := sTmp + ASQL[n];

    Inc(n);
  end;
  Result := ASQL;
end;

[其他解释]

//从SQL中提取第一个指定名称的函数信息
function GetFirstFuncInfo(ASQL, AFuncName: string; var ABegin, AEnd: integer; var AFunInfo: TSqlFuncInfo): boolean;
var
  n, n2, k, ArgBegin, ArgEnd, st, ArgCount: integer;
  sArgs: array [0..10] of string;
  sTmp: string;
begin
  Result := false;
  ArgBegin := -1; //参数开始
  ArgEnd := -1;  //参数结束
  AFunInfo.Name := AFuncName;
  AFuncName := LowerCase(AFuncName);
  n := pos(AFuncName, ASQL);
  if n <= 0 then
    Exit;
  n2 := n;
  while (n2 <= Length(ASQL)) and (ASQL[n2] <> '(') do
    Inc(n2);
  if n2 > Length(ASQL) then
    Exit;
  ArgBegin := n2 + 1;
  st := 0;
  n2 := n2 + 1;
  while (n2 <= Length(ASQL))  do
  begin
    if ASQL[n2] = '(' then
      Inc(st)      //状态机
    else
    if ASQL[n2] = ')' then
    if st = 0 then
    begin
      ArgEnd := n2 - 1;
      Break;
    end
    else
      Dec(st);
    Inc(n2);
  end;
  if ArgEnd = -1 then //参数不正确
    Exit;

  ABegin := n;
  AEnd := n2;

  sTmp := '';
  ArgCount := 0;
  k := ArgBegin; //参数开始
  st := 0; //状态机,用来处理函数嵌套的情况
  while k <= Argend do //分离参数
  begin
    if (ASQL[k] = ',') and (st = 0) then
    begin
      sArgs[ArgCount] := sTmp;
      Inc(ArgCount);
      sTmp := '';
    end
   else
      sTmp := sTmp + ASQL[k];

    if ASQL[k]= '(' then
      Inc(st)
    else
    if ASQL[k] = ')' then
      Dec(st);

    Inc(k);      
  end;

  if sTmp <> '' then
  begin        //最后一个参数
   sArgs[ArgCount] := sTmp;


   Inc(ArgCount);
  end;

  if ArgCount > 10 then
    ArgCount := 10;
  AFunInfo.ArgCount := ArgCount;
  for n := 0 to Argcount - 1 do
   AFunInfo.Args[n] := sArgs[n];
  Result := true;  
end;

//将原来的函数替换成新的函数(包括参数)
function ReplaceFunctionByNew(ASQL: string; ABegin, AEnd: integer; AFuncInf, ANewFuncInf: TSqlFuncInfo): string;
var
  sNewFunc, sArgs: string;
  i: integer;
begin
  //构造新函数的字串
  sArgs := '';
  for i := 0 to ANewFuncInf.ArgCount - 1 do
    sArgs := sArgs + ANewFuncInf.Args[i] + ',';
  if sArgs <> '' then
    Delete(sArgs, length(sArgs), 1);  
  sNewFunc := ANewFuncInf.Name + '('+ sArgs + ')';
  //替换原来的函数, ABegin 和 AEnd 是原来函数的起始位置
  Result := Copy(ASQL, 1, ABegin - 1) + sNewFunc + Copy(ASQL, AEnd + 1, length(ASQL));
end;

//替换参数一致,只是名称不同的函数
function ReplaceSameArgsFunctions(ASQL: string; AFuncName, ANewFuncName: string): string;
begin
  AFuncName := lowercase(AFuncName);
  Result := StringReplace(ASQL, AFuncName+'(', ANewFuncName + '(', [rfReplaceAll]);
  Result := StringReplace(Result, AFuncName+' (', ANewFuncName + '(', [rfReplaceAll]); //考虑函数名和括号之间有一个空格的情况
end;

function Convert_GetDate(ASQL: string): string;
var
  AFunInfo, AFuncInfoNew: TSqlFuncInfo;
  ABegin, AEnd: integer;
  sPttr: string;
begin
  Result := ASQL;
  while GetFirstFuncInfo(Result, 'getdate', ABegin, AEnd, AFunInfo) do
  begin
    Result := Copy(Result, 1, ABegin - 1) + 'SYSTIMESTAMP' + Copy(Result, AEnd + 1, Length(Result));
  end;
end;

//替换right函数
function Convert_Right(ASQL: string): string;
var
  AFunInfo, AFuncInfoNew: TSqlFuncInfo;
  ABegin, AEnd, i: integer;
  sPttr: string;
begin
  Result := ASQL;
  while GetFirstFuncInfo(Result, 'right', ABegin, AEnd, AFunInfo)  do
  begin
    if AFunInfo.ArgCount < 2 then
      Break;
    AFuncInfoNew.Name := 'SUBSTR';
    AFuncInfoNew.ArgCount := 3;
    AFuncInfoNew.Args[0] := AFunInfo.Args[0];
    AFuncInfoNew.Args[1] := ' -' + trim(AFunInfo.Args[1]);
    AFuncInfoNew.Args[2] := AFunInfo.Args[1];
    
    Result := ReplaceFunctionByNew(Result, ABegin, AEnd, AFunInfo, AFuncInfoNew);
  end;
end;

//替换Left函数
function Convert_Left(ASQL: string): string;
var
  AFunInfo, AFuncInfoNew: TSqlFuncInfo;


  ABegin, AEnd, i: integer;
  sPttr: string;
begin
  Result := ASQL;
  while GetFirstFuncInfo(Result, 'left', ABegin, AEnd, AFunInfo)  do
  begin
    if AFunInfo.ArgCount < 2 then
      Break;
    AFuncInfoNew.Name := 'SUBSTR';
    AFuncInfoNew.ArgCount := 3;
    AFuncInfoNew.Args[0] := AFunInfo.Args[0];
    AFuncInfoNew.Args[1] := ' 1';
    AFuncInfoNew.Args[2] := AFunInfo.Args[1];
    
    Result := ReplaceFunctionByNew(Result, ABegin, AEnd, AFunInfo, AFuncInfoNew);
  end;
end;

//替换Len函数
function Convert_Len(ASQL: string): string;
var
  AFunInfo, AFuncInfoNew: TSqlFuncInfo;
  ABegin, AEnd, i: integer;
  sPttr: string;
begin
  Result := ASQL;
  while GetFirstFuncInfo(Result, 'len', ABegin, AEnd, AFunInfo)  do
  begin
    if AFunInfo.ArgCount < 1 then
      Break;
    AFuncInfoNew.Name := 'LENGTH';
    AFuncInfoNew.ArgCount := 1;
    AFuncInfoNew.Args[0] := AFunInfo.Args[0];
    
    Result := ReplaceFunctionByNew(Result, ABegin, AEnd, AFunInfo, AFuncInfoNew);
  end;
end;

//替换IsNull函数
function Convert_IsNull(ASQL: string): string;
var
  AFunInfo, AFuncInfoNew: TSqlFuncInfo;
  ABegin, AEnd, i: integer;
  sPttr: string;
begin
  Result := ASQL;
  while GetFirstFuncInfo(Result, 'isnull', ABegin, AEnd, AFunInfo)  do
  begin
    if AFunInfo.ArgCount < 3 then
      Break;
    AFuncInfoNew.Name := 'NVL';
    AFuncInfoNew.ArgCount := AFunInfo.ArgCount;
    AFuncInfoNew.Args[0] := AFunInfo.Args[0];
    AFuncInfoNew.Args[1] := AFunInfo.Args[1];
    AFuncInfoNew.Args[2] := AFunInfo.Args[2];
    
    Result := ReplaceFunctionByNew(Result, ABegin, AEnd, AFunInfo, AFuncInfoNew);
  end;
end;

//替换SubString函数
function Convert_SubString(ASQL: string): string;
var
  AFunInfo, AFuncInfoNew: TSqlFuncInfo;
  ABegin, AEnd, i: integer;
  sPttr: string;
begin
  Result := ASQL;
  while GetFirstFuncInfo(Result, 'substring', ABegin, AEnd, AFunInfo)  do
  begin
    if AFunInfo.ArgCount < 3 then
      Break;
    AFuncInfoNew.Name := 'SUBSTR';
    AFuncInfoNew.ArgCount := AFunInfo.ArgCount;
    AFuncInfoNew.Args[0] := AFunInfo.Args[0];
    AFuncInfoNew.Args[1] := AFunInfo.Args[1];


    AFuncInfoNew.Args[2] := AFunInfo.Args[2];
    
    Result := ReplaceFunctionByNew(Result, ABegin, AEnd, AFunInfo, AFuncInfoNew);
  end;
end;

//替换DateDiff函数
function Convert_DateDiff(ASQL: string): string;
var
  AFunInfo: TSqlFuncInfo;
  ABegin, AEnd, i: integer;
  sPttr: string;
begin
  Result := ASQL;
  while GetFirstFuncInfo(Result, 'datediff', ABegin, AEnd, AFunInfo)  do
  begin
    if AFunInfo.ArgCount < 3 then
      Break;
    if AFunInfo.Args[0] = 'month' then
    begin
     // AFuncInfoNew.Name := 'TRUNC';
      sPttr := 'TRUNC(MONTHS_BETWEEN(' + AFunInfo.Args[2] + ' - ' + AFunInfo.Args[1] + '))';
    end
    else
    begin
     // AFuncInfoNew.Name := 'EXTRACT';
      sPttr := 'EXTRACT(' + AFunInfo.Args[0] + ' from ' + AFunInfo.Args[2] + ' - ' + AFunInfo.Args[1] + ')';
    end;
    Result := Copy(Result, 1, ABegin - 1) + sPttr + Copy(Result, AEnd + 1, Length(Result));
  //  Result := ReplaceFunctionByNew(Result, ABegin, AEnd, AFunInfo, AFuncInfoNew);
  end;
end;

function ConvertFunctions(ASQL: string): string;
begin
  Result := ReplaceSameArgsFunctions(ASQL, 'isnull', 'NVL');
  Result := ReplaceSameArgsFunctions(Result, 'substring', 'SUBSTR');
  //先替换标准写法的参数相同的函数,对于非标准写法,例如函数名和括号间有空格,后再调用专门的函数处理
  if pos('len(', Result) > 0 then
    Result := StringReplace(Result, 'len(', 'LENGTH(', [rfReplaceAll]);
  if pos('getdate()', Result) > 0 then
    Result := StringReplace(Result, 'getdate()', 'SYSTIMESTAMP', [rfReplaceAll]);

  if pos('len', Result) > 0 then
    Result := Convert_Len(Result);

  if pos('getdate', Result) > 0 then
    Result := Convert_GetDate(Result);

  if pos('right', Result) > 0 then
    Result := Convert_Right(Result);

  if pos('left', Result) > 0 then
    Result := Convert_Left(Result);

  if pos('isnull', Result) > 0 then
    Result := Convert_IsNull(Result);

  if pos('substring', Result) > 0 then
    Result := Convert_SubString(Result);

  if pos('datediff', Result) > 0 then
    Result := Convert_DateDiff(Result);

  Result := ConvertFieldAlias(Result);  
end;

function ConvertSQLToOracle(ASQL: string): string;


begin
  Result := ReplaceCommons(LowerCase(ASQL)); //替换基本的字符
  
  if pos(' top ', Result) > 0 then         //转换top N 子句
    Result := ConvertTopNWord(Result);

  Result := ConvertFunctions(Result);    //替换函数
end;

end.
[其他解释]
转换示例:

select top 100  itemcode as Code, Name2 = Discription+'adfs',  Left(Right('dfsdf' + CodeBar,10), 6), 
right('asdfads', 32) , len('adfa', 23),  DateDiff(day, GetDate(), D2 + 33) from 
oitm where IsNull(ItemCode, '') LIke '343%' and ItemCode in
 (Select  Code as Code2 From  (select Code From table2 as B) as #t1)

Oracel:


select   itemcode code, discription+'adfs' name2  ,  SUBSTR(SUBSTR('dfsdf' + codebar, -10,10), 1, 6), 
SUBSTR('asdfads', -32, 32) , LENGTH('adfa', 23),  EXTRACT(day from  d2 + 33 -  SYSTIMESTAMP) from 
oitm where ( NVL(itemcode, '') like '343%' and itemcode in
 (select  code code2 from  (select code from table2 b) T_t1)
) And ROWNUM <= 100

热点排行