摘 要: 將SQL嵌入到C語言中混合編程,程序中含有兩種不同計算模型的語句,一種是描述性的面向集合的SQL語句,一種是過程性的高級語言語句。兩種語言各有分工,SQL語句負責操縱數(shù)據庫,而C語言語句負責控制程序流程。利用高級語言的過程性結構來彌補SQL語句實現(xiàn)復雜應用系統(tǒng)方面的不足。給出了C語言與嵌入式SQL編程在不同版本SQL Server中的圖像處理應用實例。
關鍵詞: 嵌入式SQL; 圖像數(shù)據; SQL Server
SQL Server是現(xiàn)階段應用程序最普遍采用的數(shù)據庫技術,在數(shù)據庫中對圖像、視頻和聲音等數(shù)據的存取需要越來越頻繁。普通數(shù)據可直接在用戶定義的字段上存取,而這類被稱為二進制大對象(Binary Large Object)的大數(shù)據塊由于其數(shù)據量太大,不是作為數(shù)據記錄的一部分被存儲在數(shù)據記錄頁中,而是存儲在其所屬的一組專用頁中,數(shù)據表的對應字段中僅是一個十六進制的指針,該指針指向存放該記錄的頁面。由于SQL語言是一種面向集合運算的描述語言,其本身不具有過程性結構,使用SQL Server中的Image類型字段存放圖像文件時,Image類型字段是只存儲位串,SQL Server不對它進行編譯,而是由應用程序完成解釋。又因Image類型的字段內容在SQL Server 2000中不能使用INSERT和UPDATA等語句進行插入和更新,所以需編寫專門的過程來處理圖像字段。盡管在SQL Server 2005可以使用有關的函數(shù)解決這一問題,但由于實際的應用系統(tǒng)是非常復雜的,數(shù)據庫訪問只是其中一個部分,有些用戶交互、圖形化輸入輸出數(shù)據只能用高級語言實現(xiàn)。利用高級語言的過程性結構來彌補SQL語言實現(xiàn)復雜應用方面的不足, 將SQL語言嵌入到C語言的嵌入式編程將有廣泛的應用前景。
1 嵌入式SQL及語法要素
1.1 C語言嵌入式語句[1]
SQL語言可以嵌入到C語言中使用,數(shù)據庫管理系統(tǒng)一般采用的處理方法是預處理方法。預處理方法就是從含有主程序C語言和SQL語句的程序開始的。首先,把程序提交給一個專門用于C語言和SQL實現(xiàn)方式的預編譯器,預編譯器從C語言代碼中剝離SQL語句,把SQL語句轉換成C語言調用語句,以使用C語言編譯程序,并將整個編譯成目標代碼,鏈接到各數(shù)據庫并形成可執(zhí)行文件。在C語言中嵌入SQL語句產生應用程序的過程為[2]:編輯C源代碼+嵌入式SQL→SQL預編譯器→C編譯器→鏈接程序(DLL導入庫)→應用程序(數(shù)據庫)。
1.2 嵌入式SQL的語法要素
(1)創(chuàng)建嵌入式語句。將SQL嵌入到C語言中混合編程,程序中會含有兩種不同計算模型的語句。為了區(qū)別SQL語句與C語句,須在所有的SQL語句前加前綴EXEC SQL,且以分號結束,一般形式為“EXEC SQL <SQL語句>”。嵌入式語句分為可執(zhí)行語句和說明性語句,可執(zhí)行語句用來完成在交互式環(huán)境下的SQL語句中的數(shù)據定義、數(shù)據操縱和數(shù)據控制任務,說明性語句用于聲明通信區(qū)和SQL變量等。
(2)SQL通信區(qū)。SQL Server數(shù)據庫管理系統(tǒng)提供了一個通信區(qū)SQLCA,用于存儲SQL語句運行時DBMS反饋給應用程序的狀態(tài),這些信息主要描述系統(tǒng)當前工作狀態(tài)以及運行環(huán)境等。應用程序從SQLCA中取出這些狀態(tài)信息,以決定接下來執(zhí)行的語句。在C語言中定義為SQL通信區(qū)的語句為:EXEC SQL INCLUDE SQLCA。
(3)主變量。嵌入式SQL語句中可以使用C語言的程序變量及主變量來輸入或輸出數(shù)據。一個主變量可以附帶一個任選的指示變量用來指示返回給主變量的值是否為NULL值以及返回給主變量的字符串是否發(fā)生了截斷。輸入主變量出現(xiàn)于SQL語句中時,可在前面加冒號(:)以區(qū)別表字段名。而定義輸出變量用指示變量的方法,是在SQL語句EXEC SQL BEGIN DECLARE SECTION與EXEC SQL END DECLARE SECTION之間進行說明。
(4)鏈接數(shù)據庫。C程序的主函數(shù)中應包含一條登錄語句,向預編譯和程序提供用戶名和口令,以實現(xiàn)與SQL Server數(shù)據庫管理系統(tǒng)建立鏈接。其命令語法為:EXEC SQL CONNECT TO 服務器名.數(shù)據庫名AS鏈接名 USER 用戶名.口令。
2 SQL Server中圖像數(shù)據處理技術
2.1 SQL Server 2000圖像存儲方法
SQL Server 2000中,對于小于8 000 B的圖像數(shù)據可以使用二進制數(shù)據類型(binary、varbinary)表示,但通常要保存的圖像都大于8 000 B,對于這類大對像數(shù)據,系統(tǒng)提供了Image數(shù)據類型。Image數(shù)據類型不同于其他數(shù)據類型,該字段內容不能使用標準INSERT和UPDATE等語句進行插入和更新,因此用C語言程序[3]來編寫處理圖像文件,需要先將圖像文件等數(shù)據轉換成十六進制后存儲,再將Image列中的數(shù)據存儲為位串。SQL Server不能對它進行解釋,Image列數(shù)據的解釋必須由應用程序完成,這與普通的數(shù)據存儲方式是不同的。Image列所做的全部工作就是提供一個位置用來存儲組成圖像數(shù)據值的位流,這需用到SQL Server中的TEXTPTR、WRITETEXT和UPDATETEXT等函數(shù)進行圖形的添加和修改。以下是一個C語言與SQL Server 2000的嵌入式編程及圖像處理的實例,程序給出的是解決該問題的核心部分。
Demo1.sqc
#include <stdio.h>
#include <stdlib.h>
#define Buffer_Size 1024
EXEC SQL INCLUDE USERCA;
//filein為.jpg文件,fileout為.txt文件
void imagetofield(char *filein,char * fileout)
{
EXEC SQL BEGIN DECLARE SECTION;
FILE *fin,*fout; int j, Len;
unsigned char buffer1[Buffer_Size+1];
unsigned char buffer2[Buffer_Size*3+1];
unsigned char *Temp;
EXEC SQL END DECLARE SECTION;
if(!(fin=fopen(filein, "rb ")))
return;
if(!(fout=fopen(fileout", "w")))
{fclose(fin);return;}
Len=fread(buffer1, sizeof(char), Buffer_Size, fin);
Temp=buffer2;
while(Len==Buffer_Size)
{ for(j=0;j<Len;j++)
{ fprintf(fout,"%X",buffer1[j]);
Temp+= 3; };
//這樣就把二進制的數(shù)據轉換成為16進制的字符串,
并且存儲到buffer1當中了
fwrite(buffer1, sizeof(char), nLen*3, fout);
Len=fread(buffer1, sizeof(char), Buffer_Size, fin); }
fclose(fin);
fclose(fout);
……
EXEC SQL CONNECT Serverl:mydb USER sa.sa;
EXEC SQL CREATE TEALE(sno char(9), sname char
(20), resume nvarchar(max),photo image);
//表中插入一條記錄,并初始化photo字段
EXEC SQL INSERT INTO teacher VALUES (’1001’,
’Arlen’,’’,0xfffffff)
//往表中寫入圖像信息
EXEC SQL DECLARE @@tmp_data varbinary(16)
EXEC SQL SELECT @@tmp_data = TEXTPTR(photo)
FROM teacher WHERE sno= '1001 '
EXEC SQL WRITETEXT teacher.photo @@tmp_data:*fileout
//:*fileout圖像文件轉為十六進制文件指針
……
EXEC SQL COMMIT ;
EXEC SQL DISCONNECT ALL;}
2.2 SQL Server 2005圖像存儲實現(xiàn)方法[4]
SQL Server 2005 的 OPENROWSET 函數(shù)能夠一次完成遠程數(shù)據的連接與存取??梢栽?SELECT 語句的 FROM 子句中使用 OPENROWSET 函數(shù),也可以在 INSERT、UPDATE 或 DELETE 語句中把 OPENROWSET 函數(shù)當成目標數(shù)據表來使用。值得一提的是,SQL Server 2005在OPENROWSET函數(shù)中加入了BULK數(shù)據列集, 這樣可以直接從文字文件、xml 文件以及圖像等文件中讀取數(shù)據。這就意味著可以在一條非常簡單的 INSERT INTO…SELECT 語句中使用OPENROWSET函數(shù)將內含大量數(shù)據的文件內容存入數(shù)據表的對應字段(如簡歷、圖像等)中。OPENROWSET BULK選項自變量可以精確控制數(shù)據讀取的開始與結束位置、如何處理錯誤以及數(shù)據的解釋,例如將數(shù)據文件讀取成 varbinary、varchar 或 nvarchar 類型的字段的數(shù)據列集。以下是一個C語言與SQL Server 2005的嵌入式編程及圖像處理的實例,程序給出的是解決這一問題的核心部分。
Demo2.sqc
#include <stdio.h>
#include <stdlib.h>
EXEC SQL BEGIN DECLARE SECTION;
char sno[10],sname[10];int ssex;
EXEC SQL END DECLARE SECTION ;
EXEC SQL INCLUDE USERCA;
viod imagetech ()
{ EXEC SQL CONNECT TO Server:mydb USER sa.sa;
EXEC SQL CREATE TABLE Teacher
(sno char(9), sname char(20), ssex int,
resume nvarchar(max),
//創(chuàng)建可輸入大數(shù)據塊文本的簡歷字段
photo image);
printf( "input sno: "); scanf( "%s",sno);
printf( "input sname: "); scanf( "%s",sname);
printf( "input?ssex: "); scanf( "%d",&ssex);
EXEC SQL INSERT INTO Teacher(sno,sname,ssex,resume,
photo)
SELECT :sno, :sname, :ssex,
WSET(BULK ’C:\resume1.txt’, SINGLE_NCLOB),
OPENROWSET(BULK ’C:\photo1.jpg’, SINGLE_BLOB);
//一種大數(shù)據塊及圖像存儲的解決方案
EXEC SQL COMMIT TRANSACTION;
EXEC SQL DISCONNECT ALL;
}
2.3 預編譯
C語言編譯程序不能識別應用程序中的SQL語句,需要經過預處理程序將其轉換成C語句。經過嵌入式SQL的預編譯之后,原有的嵌入式SQL會被轉換成一系列函數(shù)調用。因此,系統(tǒng)還提供一些列函數(shù)庫,以確保能夠把代碼中的函數(shù)調用與對應的實現(xiàn)鏈接起來。SQL Server的預處理程序是nsqlprep.exe。通過在操作系統(tǒng)命令窗口運行命令cd c:\program files\Microsoft SQL Server\MSSQL\Binn,進入到Binn文件夾,調用預編譯程序nsqlprep.exe程序,執(zhí)行nsqlprep Demo2,如果成功就會將Demo2.sqc文件預編譯成Demo2.c。接著運行主語言編譯程序VC++,打開Demo2.c進行編譯,VC++會提示要建立工程,點擊“是”建立工程文件。還需在工程/設置/link中的對象/庫模塊中添加SQLakw32.lib和Caw32.lib才能夠正確鏈接,最后生成目標程序和可執(zhí)行文件。
當一個程序既要訪問數(shù)據庫,又要處理數(shù)據時,把SQL語言嵌入到宿主語言中,將SQL語言訪問數(shù)據庫的功能和宿主語言的數(shù)據處理功能相結合是解決該問題的有效途徑。圖像處理作為一種信息表達手段已被人們所熟悉,在數(shù)據庫信息管理系統(tǒng)的開發(fā)中[5]需要用到圖像等數(shù)據時,將有關信息與指定的圖像對應,無疑對圖像數(shù)據處理的科研、生產和管理等部門有著重要的實用參考價值。因此,在嵌入式SQL中用數(shù)據庫管理系統(tǒng)的預編譯器技術,無限利用高級語言通過數(shù)據庫管理系統(tǒng)的接口存取和檢索數(shù)據,來提高對數(shù)據庫操作的效率提高。
參考文獻
[1] 王珊,薩師煊.數(shù)據庫系統(tǒng)概論(第4版)[M].北京:高等教育出版社,2006.
[2] 高守傳,劉小靜.使用嵌入式SQL訪問數(shù)據庫[J].電腦編程技巧與維護,2007(2):73-77.
[3] 譚浩強. C程序設計[M].北京:清華大學出版社,2010.
[4] 劉衛(wèi)國,熊擁軍.數(shù)據庫技術與應用[M].北京:清華大學出版社,2010.
[5] 劉玉海.MIS圖像輸出模塊設計[J].微型電腦應用,1996(4):63-65.