动态准备SQL语句的逻辑

时间:2017-02-08 08:45:21

标签: sql db2 ibm-midrange rpgle

所以我有一个要求,我需要读取文件所有记录的记录,如果它们符合另一个表中描述的一组规则,则将它们插入到另一个文件中,如下所示。

enter image description here

从第一个文件中读取后的记录必须满足至少一个规则的所有序列,才能使其有资格写入第二个表。

例如,一旦从CAR文件中读取记录,就必须检查以下规则,直到满足至少一个规则集的所有序列。为此,我计划创建一个这种类似的动态SQL程序。但这不起作用,因为Prepared SQL不支持宿主变量。

enter image description here

如果任何机构可以建议或提供有关如何动态创建SQL状态码的任何指导,并检查记录是否满足将它们输入第二个文件所需的规则,那就太棒了

基本上我正在寻找的是一旦我从表中选择一个字段,我该如何存储它以进行进一步的验证和检查。

  

更新

根据Danny117的智能建议,我提出了以下代码:

H Option(*NoDebugIO:*SrcStmt)                                    
D RULEDS        E DS                  EXTNAME(RULESTABLE)        
D MAXRUL          S              1  0                            
D MAXSEQ          S              1  0                            
D STMT            S            512                               
D WHERESTMT       S            512    INZ('')                    
D FullSqlStmt     S            512    INZ('')                    
D RULINDEX        S              1  0 INZ(1)                     
D SEQINDEX        S              1  0 INZ(1)                     
D APOS            C                   CONST('''')                
  /Free                                                          
    Exec SQL SELECT MAX(RULENO)INTO :MAXRUL FROM RULESTABLE;     
    Exec SQL DECLARE RULCRS CURSOR FOR SELECT * FROM RULESTABLE; 
    Exec SQL OPEN RULCRS;                                        
    Exec SQL FETCH RULCRS INTO :RULEDS;                          
    DoW (Sqlcod = 0 AND RULINDEX <= MAXRUL);                     
      Exec SQL SELECT MAX(SEQNO) INTO :MAXSEQ FROM RULESTABLE    
      WHERE RULENO=:RULINDEX ;                                   
      DoW (SEQINDEX <= MAXSEQ);                                  
   If (Position <> '');                                     
     Field = 'SUBSTR('+%Trim(Field)+','+%Trim(Position)+',' 
     +'1'+')';                                              
   EndIf;                                                   
   WhereStmt = %Trim(WhereStmt) + ' ' + %Trim(field)+ ' ' + 
   %Trim(condition) + ' ' + APOS + %Trim(Value) + APOS;     

   If (SeqIndex < MaxSeq);                                  
     WhereStmt = %Trim(WhereStmt) + ' AND ';                
   EndIf;                                                   


   Exec SQL FETCH NEXT FROM RULCRS INTO :RULEDS;            
   SeqIndex = SeqIndex + 1;                                 
 EndDo;                                                     
 FullSqlStmt = %Trim('INSERT INTO ITMRVAT SELECT * +        
 FROM ITMRVA WHERE '+ %Trim(WhereStmt));                    
 Exec SQL Prepare InsertStmt from :FullSqlStmt;             
 Exec SQL EXECUTE InsertStmt;                               
  RulIndex = RulIndex + 1;
EndDo;   

这会产生如下所示的SQL语句,这就是我想要的。现在让我继续看看代码的其他部分。

 > EVAL FullSqlStmt                                                       
  FULLSQLSTMT =                                                          
            ....5...10...15...20...25...30...35...40...45...50...55...60 
       1   'INSERT INTO ITMRVAT SELECT * FROM ITMRVA WHERE STID = 'PLD' '
      61   'AND ENGNO LIKE '%415015%' AND SUBSTR(ENGNO,1,1) = 'R' AND SU'
     121   'BSTR(ENGNO,5,1) = 'Y'                                       '
     181   '                                                            '
     241   '                                                            '
     301   '                                                            '
     361   '                                                            '
     421   '                                                            '
     481   '                                '                            

但问题现在正如我在对Danny的评论中提到的,如果指定了涉及第二个表的新规则,如何处理..

2 个答案:

答案 0 :(得分:3)

嵌入式SQL确实允许ILE语言中的“动态语句”。您可以在字符字段中进行查询,然后将其传递给嵌入式SQL。

$Path="C:\abc\"
$itemFolders = Get-ChildItem $Path
#Get All Folders inside
$AllFolders = $itemFolders | Get-ChildItem -Recurse | Where-Object {$_.PSIsContainer} | Select -Property FullName
#First delete all files older than 30 days
$itemFolders | Get-ChildItem -Recurse -File | ForEach-Object{
    $limit = (Get-Date).AddDays(-30)
    if($_.LastWriteTime -lt $limit)
    {
        "{0} hasn't been modified in the last 30 days deleting it" -f $_.FullName
        Remove-Item -Path $_.FullName -Force -ErrorAction SilentlyContinue        
    }
}
#Check if there are files inside that are not containers
$AllFolders | ForEach-Object{
    $files = Get-ChildItem -File -Recurse -Path $_.FullName
    $directories = Get-ChildItem -Directory -Recurse -Path $_.FullName

    #If There are any files inside the folder dont delete it.
    if($files.Count -gt 0)
    {
        "Found {0} files inside {1} do not delete this" -f $files.Count, $_.FullName
    }
    #If There are no files and no directories inside delete it.
    elseif($files.Count -eq 0 -and $directories.Count -eq 0)
    {
        "Empty Folder {0} deleting it" -f $_.FullName
        Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue
    }
    #If there are no files and empty directories inside delete it.
    elseif($files.Count -eq 0 -and $directories.Count -gt 0)
    {
        "No Files but directories found in {0} since its recursive delete it" -f $_.FullName
        Remove-Item -Path $_.FullName -Recurse -Force -ErrorAction SilentlyContinue        
    }
}

您可能只想准备,执行并返回结果集:

Dcl-S lQuery Varchar(100);

lQuery = 'SELECT * FROM CUST';

EXEC SQL
  PREPARE SCust FROM :lQuery;
EXEC SQL
  DECLARE SearchCust CURSOR FOR SCust;

//Continue working with cursor..

可选附加:您可能还想在查询中使用字段标记(?)。

lQuery = 'SELECT * FROM CUST WHERE ID = ' + %Char(CustID);

EXEC SQL
  PREPARE SCust FROM :lQuery;

DECLARE c1 CURSOR FOR SCust;
OPEN c1;
FETCH c1 INTO :CustDS;
CLOSE c1;

答案 1 :(得分:0)

您必须将规则转换为join语句或where子句。 join语句更复杂,所以走那条路。

如果您很聪明(并且您是),请考虑将规则保存为可以在where子句中加入或使用的SQL子句。它的无限灵活性是一种更现代的设计。

规则1 / car.year = 1990和car.engno喜欢&#39;%43243%&#39;和子串(car.vin,12,1)=&#39; X&#39;

eval statement = 
insert into sometable
Select car.* from car  
join sysibm.sysdummy1 
on car.year = 1990 
and car.engno lile '%43243%' 
从&#34; OR&#34;

开始,

......等到规则2

or car.year = PLD
and car.engno like '%1234%'

...等以&#34; OR&#34;

开头的其他规则
exec immediate statement