VFP小函式

SQL字串轉換postgresql

作者:cschen33.tw@yahoo.com.tw
最後更新日期:2004/04/07
程式:sql_string.prg

我在寫VFP6.0資料庫時,後端 使用postgresql時,會碰到一個很煩的問題就 是vfp的sql指令和postgresql的並不是很相容,又因為使用ODBC因此sql指令撰寫者要先將其變成字串,因此在下sql指令時必須要做一 些字串的轉換,才能正確的執行。
以下是自行轉換為字串,例:
sql_string="UPDATE op_service_code set "+name_value+ " where code='" +CODE+"'"
上述只是設定一個更新的欄位如果是10個,則字串可能要兩三行,而且易寫錯,字串要加'',數字不用及一堆+,""等。為了簡化這個工作,我寫了一個 vfp的小函式來做這個轉換,例:
sql_string="update op_service_code set m.name_value where code=m.code"
使用函式parse_string
sql_string=parse_string(sql_string)
它會將m.啟始的字串用變數取代

比較:
原:
sql_string="UPDATE op_service_code set "+name_value+ " where code='" +CODE+"'"
後:
sql_string="update op_service_code set m.name_value where code=m.code"
sql_string=parse_string(sql_string)


以下是一些問題及想法
  1. 原想使用函式套陣列進去,但會破壞程式撰寫人下sql指令的直覺
  2. 直接下sql指令就好了,而字串中凡是變數均要使用m.開頭的記憶體變數(一般是表格名稱或欄位值)
  3. 所有字串中使用的記憶體變數必須使用m.,並定義為公共變數,之所以這麼做是因為要如果要傳遞變數,可能要用陣列才可以,再來一般在撰寫本來 就常定義資料庫的記錄欄位為公共變數
  4. sql的指令包含了select,update,delete,insert
  5. vfp專有的指insert into m.table from memvar 不可使用
  6. 對於數字部份,因為在轉換的過程中會有小數點的問題,我限制了15位整數及5位小數,超過者請自行修改程式
  7. 將字串變成陣列,以分隔符號"空白,逗點,()括號,及大小等於><=,由於分隔符號可能有二個,所以在合併時,檢查字串尾及要 加入字串的陣列

程式在此,其它的應用請自已發揮

PROCEDURE parse_sqlstring
LPARAMETERS sql_string
sql_string=UPPER(sql_string)

判斷使用的指令是insert,delete,update,select 的那一個
is_insert=ATC("insert",sql_string)
is_delete=ATC("delete",sql_string)
is_update=ATC("update",sql_string)
is_select=ATC("select",sql_string)
i=1
*建立分隔號在字串中位置的陣列,包含了空格、左括號"("、右括號")"、逗點","、等號=,>,<,<>,>=,<=
sep_string=" ,()<>="
array_len=0
FOR j=1 TO LEN(sep_string)
sep_element=SUBSTR(sep_string,j,1)
i=1
DO WHILE ATC(sep_element,sql_string,i)>0
array_len=array_len+1
DIMENSION sep[array_len]
sep[array_len]=ATC(sep_element,sql_string,i)
i=i+1
ENDDO
ENDFOR
*排序(由小而大)
=ASORT(sep)

*根據分符號來分割字串建立字串陣列,分割符號也要放在陣列中
*i=1 的字串必定存在,去掉空白的陣列元素

FOR i =1 TO ALEN(sep)
IF i=1
DIMENSION m_array[1]
t_string=SUBSTR(sql_string,1,sep[i]-1)
m_array[1]=t_string
t_string=ALLT(SUBSTR(sql_string,sep[i],1))
IF !EMPTY(t_string)
DIMENSION m_array[2]
m_array[2]=t_string
ENDIF
ELSE
t_string=ALLT(SUBSTR(sql_string,sep[i-1]+1,sep[i]-sep[i-1]-1))
IF !EMPTY(t_string)
array_len=ALEN(m_array)+1
DIMENSION m_array[array_len]
m_array[array_len]=t_string
ENDIF
t_string=ALLT(SUBSTR(sql_string,sep[i],1))
IF !EMPTY(t_string)
array_len=ALEN(m_array)+1
DIMENSION m_array[array_len]
m_array[array_len]=t_string
ENDIF
ENDIF
ENDFOR
sep_len=ALEN(sep)
IF sep[sep_len]<LEN(sql_string)
array_len=ALEN(m_array)+1
DIMENSION m_array[array_len]
m_array[array_len]=SUBSTR(sql_string,sep[sep_len]+1)
ENDIF

RELEASE i,j,sep
*尋找陣列中的表格名稱是否是變數,如果是變數取代
table_name=""
table_position=0
DO CASE
CASE is_insert>0
IF ASCAN(m_array,"INTO")>0
table_position=ASCAN(m_array,"INTO")+1
table_name=m_array[table_position]
ENDIF
CASE is_delete>0
IF ASCAN(m_array,"FROM")>0
table_position= ASCAN(m_array,"FROM")+1
table_name=m_array[table_position]
ENDIF
CASE is_update>0
IF ASCAN(m_array,"UPDATE")>0
table_position= ASCAN(m_array,"UPDATE")+1
table_name=m_array[table_position]
ENDIF
CASE is_select>0
IF ASCAN(m_array,"FROM")>0
table_position=ASCAN(m_array,"FROM")+1
table_name=m_array[table_position]
ENDIF
OTHERWISE

ENDCASE
IF SUBSTR(ALLTRIM(table_name),1,2)="M."
m_array[table_position]=&table_name
ENDIF
*尋找其它的變數取代之
i=1
FOR EACH element IN m_array
IF LEFT(element ,2)=="M."
IF TYPE("&element")=="C"
m_array[i]="'"+&element+"'"
ELSE
m_array[i]=&element
ENDIF
ENDIF
i=i+1
ENDFOR
*針對數字部份,如果非有小數點去掉小數點及以下
return_string =""
FOR i=1 TO ALEN(m_array)
IF !EMPTY(m_array[i])
IF TYPE("m_array[i]")=="N"
t_value=ALLTRIM(STR(m_array[i],20,5))
DO WHILE INLIST(RIGHT(t_value,1),"0" ,".")
t_value=SUBSTR(t_value,1,LEN(t_value)-1)
ENDDO
return_string=return_string+" "+t_value
ELSE
*判別>=,<=,<>的狀況
IF INLIST(RIGHT(return_string,1),">","<") AND INLIST(m_array[i],"=",">")
return_string=return_string+m_array[i]
ELSE
return_string=return_string+" "+m_array[i]
ENDIF
ENDIF
ENDIF
ENDFOR
return_string=ALLTRIM(return_string)
RETURN return_string
ENDPROC