How to get the SQL content of the stored procedure in Delphi code? - sql-server

I'm debugging Delphi code with Delphi 7 IDE, the code is not mine. My goal is to understand how this code works. This will help me to write my application which will interface with this code.
I never used Delphi in my life. I'm a C, C++, C# programmer.
I'm able to see the output (result) of the stored procedure but I need to see the content of the stored procedure (I mean the SQL statement). I looked in SQL Server side but I didn't find anything.
The stored procedure is called in this function :
function TDBDM.getID( prKeyName : string ) : integer;
begin
try
spGetSN.Parameters.ParamValues['#prKeyname'] := prKeyName;
spGetSN.open;
result := spGetSN.Fields[0].AsInteger;
finally
spGetSN.close;
end;
end;
and the stored procedure 'spGetSN' is declared here :
unit dmDB;
interface
uses
SysUtils, Classes, Forms, ADODB, DB, TypInfo, Dialogs, StdCtrls,
Controls,Registry, Windows;
type
eConnectionType = (ctSN);
TDBDM = class(TDataModule)
ADOConnectionSN: TADOConnection;
spGetSN: TADOStoredProc;
ADOQueryGetPartNoFromRMA: TADOQuery;
ADOQueryGetPartNoFromOrder: TADOQuery;
procedure ADOConnectionSNBeforeConnect(Sender: TObject);
procedure DataModuleCreate(Sender: TObject);
private
{ Private declarations }
function GetConnection( prConnectionType : eConnectionType ) :
TADOConnection;
public
{ Public declarations }
function getID( prKeyName : string ) : integer;
function getSN( prKeyName : string ) : string;
function getCommaValues( prSelect : string; prConnection :
eConnectionType = ctSN ) : string;
property pConnection[prType : eConnectionType] : TADOConnection read
GetConnection; default;
end;
var
DBDM: TDBDM;
implementation
uses dmRegistryClasses;
{$R *.dfm}
The text of the object TADOSTOREDPROC 'spGetSN' as defined in the IDE is :
object spGetSN: TADOStoredProc
Connection = ADOConnectionSN
ProcedureName = 'spGetSN;1'
Parameters = <
item
Name = '#RETURN_VALUE'
DataType = ftInteger
Direction = pdReturnValue
Precision = 10
Value = Null
end
item
Name = '#prKeyname'
Attributes = [paNullable]
DataType = ftWideString
Size = 30
Value = Null
end>
Left = 268
Top = 80
end
How can I print or watch the SQL code of this stored procedure in Delphi debugger? Thanks

The following should give you an idea how to do it:
Add a TAdoQuery called AdoQuerySP to your form and set its connection to whatever AdoConnection component you're using at the moment.
Add a TMemo to the form.
Add a TButton to the form and set its OnClick handler to execute the code below (after changing checklibuse to the name of your SP).
Code:
procedure TForm1.GetSPDefinition;
var
S : String;
begin
S := '';
AdoQuerySP.Sql.Text := 'exec sp_helptext checklibuse'; // sp_helptext
// is a Sql Server system stored proc to retrieve the definition of
// a stored proc. The definition is returned as a series of rows which need to be
// concatenated together as in the `while ...` loop below.
AdoQuerySP.Open;
while not AdoQuerySP.Eof do begin
if S <> '' then
S := #13#10 + S;
S := S + AdoQuerySP.FieldByName('Text').AsString;
AdoQuerySP.Next;
end;
// The retrieved definition is typically preceded by a number of blank lines
// which the call to Trim() remove.
Memo1.Lines.Text := Trim(S);
end;

You could query the sys.sql_modules table e.g.:
function MSSQL_GetModuleText(conn: TADOConnection; const ModuleName: WideString): WideString;
var
SQL: WideString;
rs: Variant;
begin
SQL := Format('SELECT [definition] FROM sys.sql_modules WHERE [object_id]=OBJECT_ID(N''%s'')', [ModuleName]);
rs := conn.Execute(SQL);
Result := VarToWideStr(rs.Fields[0]);
end;
Usage:
S := MSSQL_GetModuleText(ADOConnectionSN, 'dbo.spGetSN');

Related

Delphi TFDStoredProc parameter default values missing (MS SQL)

I am migrating from ADO to FireDAC. After replacing TADOStoredProc to TFDStoredProc I have the following issue. My _OpenStp procedure opens a stored procedure having default values in its parameter list, and I don't want to pass all those parameters. E.g.
CREATE PROCEDURE [dbo].[usp_SearchDocument]
#User_Id INT
, #Window_Id INT = 10
, #Page INT = 1
...
The core of my procedure:
procedure _OpenStp(
const AConnection: TFDConnection;
var AStp: TFDStoredProc;
const AStpName: string;
const AParamNameA: array of string;
const AParamValueA: array of Variant);
var
i: Integer;
begin
if AStp <> nil then
begin
if AStp.Active then
AStp.Close;
end
else
AStp := TFDStoredProc.Create(nil);
AStp.Connection := AConnection;
AStp.StoredProcName := AStpName;
AStp.Prepare;
for i := Low(AParamNameA) to High(AParamNameA) do
AStp.Params.ParamByName(AParamNameA[i]).Value := AParamValueA[i];
AStp.Open;
end;
The Delphi code of the call:
_OpenStp(SomeConnection, SomeStp, 'usp_SearchDocument',
['User_Id'], [150]);
According to SQL Server Profiler the call was:
exec [dbo].[usp_SearchDocument]
#User_Id=150,
#Window_Id=NULL,
#Page=NULL
TFDStoredProc.Prepare doesn't seem to query the default values of the sp parameters. When I was using the ADO counterpart of my _OpenStp procedure, the TADOStoredProc.Parameters.Refresh method did that job:
procedure _OpenStp(
const AConnection: TADOConnection;
var AStp: TADOStoredProc;
const AStpName: string;
const AParamNameA: array of string;
const AParamValueA: array of Variant);
begin
if AStp <> nil then
begin
if AStp.Active then
AStp.Close;
end
else
AStp := TADOStoredProc.Create(nil);
AStp.Connection := AConnection;
AStp.ProcedureName := AStpName;
AStp.Parameters.Refresh;
for i := 0 to Length(AParamNameA) - 1 do
AStp.Parameters.ParamByName(AParamNameA[i]).Value := AParamValueA[i];
AStp.Open;
end;
SQL Server Profiler:
exec usp_SearchDocument 150,default,default
Unfortunately it isn't an option to rewrite the code to pass all of the parameters, I have to rely on sp parameter default values. Is there a way to modify the FireDAC version of my _OpenStp procedure to achieve this goal?
Edit: I don't even have information about the type of the parameters (see the _OpenStp procedure), I only know their names and the values to be set, so I can't create the TFDParams programmatically.
Edit#2: An EArgumentOutOfRangeException was thrown after deleting the unnecessary parameters:
for i := AStp.ParamCount - 1 downto 0 do
if AStp.Params[i].Name <> '#RETURN_VALUE' then
begin
ExistsInArray := False;
for j := Low(AParamNameA) to High(AParamNameA) do
if Char.ToLower(AStp.Params[i].Name) = Char.ToLower(Format('#%s', [AParamNameA[j]])) then
begin
ExistsInArray := True;
Break;
end;
if not ExistsInArray then
AStp.Params.Delete(i);
end;

How to migrate from ADO Filtering code to Firedac

I have this code:
datamodule1.tbabonne.Filter := '';
if (scGPEdit2.Text) = '' then exit ;
try
ref_Abonne:= QuotedStr (scGPEdit2.Text + '*');
if (scGPEdit2.Text <> '') then
datamodule1.tbabonne.Filter:= Format('(ref_Abonne LIKE %s)', [ref_abonne])
else
datamodule1.tbabonne.Filtered := Trim((scGPEdit2.Text)) <> '' ;
except
abort;
end;
//edit1.Text := '';
end;
My question is :
the code Above didn't work with Firedac while is working as charm in ADO
In FireDAC filters, the wildcards are _ for a single character and % for multiple characters - see http://docwiki.embarcadero.com/Libraries/Sydney/en/FireDAC.Comp.Client.TFDQuery.Filter which gives this example
You can use standard SQL wildcards such as percent (%) and underscore (_) in the condition when you use the LIKE operator. The following filter condition retrieves all Countries beginning with 'F'
Country LIKE 'F%'
So you need to adjust your line
ref_abonne:= QuotedStr (scGPEdit2.Text + '*');
accordingly, to use the LIKE operator and the % wildcard.
Just guessing but maybe ADO used the * wildcard and = operator to insulate e.g. VB users from SQL wildcards and syntax.
UpdateHere is a sample project which uses the FireDAC % wildcard and LIKE operator
in a filter. Take careful note of the inline comments.
TForm1 = class(TForm)
// Create a new VCL project and drop the following components
// onto it. There is no need to set any of their properties
FDMemTable1: TFDMemTable;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
edFilter: TEdit;
// Use the Object Inspector to create the following event handlers
// and add the code shown in the implementation section to them
procedure FormCreate(Sender: TObject);
procedure edFilterChange(Sender: TObject);
public
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.edFilterChange(Sender: TObject);
begin
UpdateFilter;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
DBGrid1.DataSource := DataSource1;
DataSource1.DataSet := FDMemTable1;
// Adjust the following line to suit the location of Employee.Fds on your system
FDMemTable1.LoadFromFile('D:\D10Samples\Data\Employee.Fds');
FDMemTable1.IndexFieldNames := 'LastName;FirstName';
FDMemTable1.Open;
FDMemTable1.First;
// Make the filter disregard string case
FDMemTable1.FilterOptions := [foCaseInsensitive];
UpdateFilter;
end;
procedure TForm1.UpdateFilter;
var
FilterExpr : String;
begin
FilterExpr := edFilter.Text;
if FilterExpr <> '' then
FilterExpr := 'LastName Like ' + QuotedStr(FilterExpr + '%');
FDMemTable1.Filter := FilterExpr;
FDMemTable1.Filtered := FDMemTable1.Filter <> '';
end;
Then just compile and run

Aggregate of multiple UI controls bound to one database column

I currently have a TDBRadioGroup bound to a CHAR column on the database using the Values property to specify the value stored in the database column for each radio button. Now we have a requirement to add 2 new radio groups along side the existing one that would modify the value. In other words I basically need 3 controls on the form to act as one in a data-aware configuration for the purposes of determining the value stored. A simple example might be if each radio group has a one-character value, and in the database you concatenate them into a 3-character string. Our mapping is more complex than that but that's the general idea. What would be a good way to do this? If someone tells me live bindings would be the way to go, that would be good to know, as it would be help me to convince management to upgrade Delphi. We're stuck on XE.
Interesting q!
I hope I've understood you correctly. Suppose there is a form with 3 radiogroups, one per line, like so
*A B C
D *E F
G H *I
where the asterisks indicates the positions of the selected buttons and suppose
that these settings translate into a field value AEI in a row of a dataset.
If the G entry of the 3rd RG is clicked, the dataset field value should become
GEI. That's what I've assumed you are looking for.
The code below is a "proof of concept" which implements the above functionality.
It does so using 3 standard (non-db-aware) TRadioGroups and an adaptor class
TDBRadioGroupAdaptor which makes these operate as db-aware RadioGroups. The
TDBRadioGroupAdaptor uses a descendant, TRGFieldDataLink, of the standard TFieldDataLink (see DBCtrls.Pas)
to interface with the dataset. I've used a TClientDataSet so the project can be completely
self-contained and I've avoided the use of generices as you didn't specify a Delphi version.
Most of the db-aware functionality is contained in the TRGFieldDataLink, which
serves to interface the dataset and the RadioGroups and differs from a standard
TFieldDataLink in that it treats the field value as composed of N (3 in the code example but it supports an arbitrary number)
sub-fields which each have their own RadioGroup. As ever with implementing db-aware
functionality, the code for the TDBRadioGroupAdaptor and TRGFieldDataLink is fairly
long-winded, as most of it is necessary but not very interesting. About the only
ones that are interesting, in that they make the wheels go around, are
function TRGFieldDataLink.GetGroupString : String;
// Returns a string from the ItemIndexes of the RadioGroups
procedure TRGFieldDataLink.GetGroupValues;
// Sets the DataSet field from the RadioGroup ItemIndexes
which I hope are self-explanatory from the embedded comments.
Because it's only supposed to be a proof-of-concept, the implementation is incomplete,
lacking f.i. keyboard support, but that could easily be added by mimicking the
source code of the standard TDBRadioGroup.
Obviously, something similar could be used to treat subfields of a dataset field as
a group of strings independently editable in a group of TEdits.
Also obviously, it would be possible to turn the TDBRadioGroupAdaptor into a full-blown compound component which includes its own radiogroups, but I've left that as an exercise for the reader.
Code (warning: long!)
type
TDBRadioGroupAdaptor = class;
TRGFieldDataLink = class(TFieldDataLink)
private
FAdaptor: TDBRadioGroupAdaptor;
FRecordChanging : Boolean;
procedure GetGroupValues;
function GetGroupString: String;
procedure SetGroupValues(AValue: String);
public
constructor Create(AAdaptor : TDBRadioGroupAdaptor);
destructor Destroy; override;
procedure RecordChanged(Field : TField); override;
procedure UpdateData; override;
property Adaptor : TDBRadioGroupAdaptor read FAdaptor write FAdaptor;
end;
TDBRadioGroupAdaptor = class
private
FDataLink : TRGFieldDataLink;
FRadioGroups : TList;
procedure SetDataSource(Value : TDataSource);
function GetDataSource : TDataSource;
function GetRadioGroup(Index: Integer): TRadioGroup;
procedure ItemClicked(Sender : TObject);
procedure SetFieldName(const Value: string);
function GetFieldName : String;
public
constructor Create;
destructor Destroy; override;
procedure Add(ARadioGroup : TRadioGroup);
property DataSource : TDataSource read GetDataSource write SetDataSource;
property FieldName : string read GetFieldName write SetFieldName;
property RadioGroup[Index : Integer] : TRadioGroup read GetRadioGroup;
end;
type
TForm1 = class(TForm)
DBGrid1: TDBGrid;
ClientDataSet1: TClientDataSet;
DataSource1: TDataSource;
DBNavigator1: TDBNavigator;
Button1: TButton;
RadioGroup1: TRadioGroup;
RadioGroup2: TRadioGroup;
RadioGroup3: TRadioGroup;
DBEdit1: TDBEdit;
DBRadioGroup1: TDBRadioGroup;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
protected
public
Adaptor : TDBRadioGroupAdaptor;
end;
[...]
{ TRGFieldDataLink }
constructor TRGFieldDataLink.Create(AAdaptor : TDBRadioGroupAdaptor);
begin
inherited Create;
Adaptor := AAdaptor;
end;
destructor TRGFieldDataLink.Destroy;
begin
inherited;
end;
procedure TRGFieldDataLink.SetGroupValues(AValue : String);
// Sets the ItemIndexes of the RadioGroups by matching each character of AValue
// to the contents of their Items
var
i,
Index : Integer;
S : String;
begin
if AValue = '' then Exit; // To avoid error when CreateDataSet is called
for i := 0 to Adaptor.FRadioGroups.Count - 1 do begin
S := AValue[i + 1];
Index := Adaptor.RadioGroup[i].Items.IndexOf(S);
Adaptor.RadioGroup[i].ItemIndex := Index;
end;
end;
procedure TRGFieldDataLink.RecordChanged(Field : TField);
// called when the dataset goes to a new record, e.g. during scrolling
// and sets the RadioGroups' ItemIndexes from the dataset data
var
FieldValue : String;
begin
Assert(DataSet <> Nil);
if FRecordChanging then exit; // just in case, avoid re-entrancy
try
FRecordChanging := True;
if Field = Nil then
Field := DataSet.FieldByName(FieldName); // Yukky way of setting Field
FieldValue := Field.AsString;
SetGroupValues(FieldValue);
finally
FRecordChanging := False;
end;
end;
function TRGFieldDataLink.GetGroupString : String;
// Returns a string from the ItemIndexes of the RadioGroups
var
i : Integer;
S : String;
begin
Result := '';
for i := 0 to Adaptor.FRadioGroups.Count - 1 do begin
S := Adaptor.RadioGroup[i].Items[Adaptor.RadioGroup[i].ItemIndex];
Result := Result + S [1];
end;
end;
procedure TRGFieldDataLink.GetGroupValues;
// Sets the DataSet field from the RadioGroup ItemIndexes
var
FieldValue,
S : String;
begin
Assert(DataSet <> Nil);
S := Field.AsString;
FieldValue := GetGroupString;
Field.AsString := FieldValue;
end;
procedure TRGFieldDataLink.UpdateData;
// Called by RTL to update the dataset record from the RadioGroups
begin
GetGroupValues;
end;
{ TDBRadioGroupAdaptor }
procedure TDBRadioGroupAdaptor.Add(ARadioGroup: TRadioGroup);
begin
FRadioGroups.Add(ARadioGroup);
ARadioGroup.OnClick := ItemClicked;
end;
constructor TDBRadioGroupAdaptor.Create;
begin
inherited;
FRadioGroups := TList.Create;
FDataLink := TRGFieldDataLink.Create(Self);
end;
destructor TDBRadioGroupAdaptor.Destroy;
begin
FDataLink.Free;
FRadioGroups.Free;
inherited Destroy;
end;
function TDBRadioGroupAdaptor.GetDataSource: TDataSource;
begin
Result := FDataLink.DataSource;
end;
procedure TDBRadioGroupAdaptor.SetDataSource(Value: TDataSource);
begin
FDataLink.DataSource := Value;
end;
function TDBRadioGroupAdaptor.GetRadioGroup(Index: Integer): TRadioGroup;
begin
Result := TRadioGroup(FRadioGroups[Index]);
end;
procedure TDBRadioGroupAdaptor.ItemClicked(Sender: TObject);
// Responds to one of the RadioGroups being clicked to put the DataSet into Edit state
// and updates the DataSet field from the ItemIndexes of the RadioGroups
var
S : String;
begin
if not FDataLink.FRecordChanging then begin
S := FDataLink.GetGroupString;
FDataLink.Edit;
FDataLink.SetGroupValues(S);
end;
end;
procedure TDBRadioGroupAdaptor.SetFieldName(const Value: string);
begin
FDataLink.FieldName := Value;
end;
function TDBRadioGroupAdaptor.GetFieldName: string;
begin
Result := FDataLink.FieldName;
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Field : TField;
begin
// Create 2 fields in the CDS
Field := TIntegerField.Create(Self);
Field.FieldName := 'ID';
Field.FieldKind := fkData;
Field.DataSet := ClientDataSet1;
Field := TStringField.Create(Self);
Field.FieldName := 'Value';
Field.Size := 40;
Field.FieldKind := fkData;
Field.DataSet := ClientDataSet1;
RadioGroup1.Items.Add('A');
RadioGroup1.Items.Add('B');
RadioGroup1.Items.Add('C');
RadioGroup2.Items.Add('D');
RadioGroup2.Items.Add('E');
RadioGroup2.Items.Add('F');
RadioGroup3.Items.Add('G');
RadioGroup3.Items.Add('H');
RadioGroup3.Items.Add('I');
Adaptor := TDBRadioGroupAdaptor.Create;
Adaptor.Add(RadioGroup1);
Adaptor.Add(RadioGroup2);
Adaptor.Add(RadioGroup3);
Adaptor.DataSource := DataSource1;
Adaptor.FieldName := 'Value';
// Next, set up the CDS
ClientDataSet1.CreateDataSet;
ClientDataSet1.InsertRecord([1, 'AEI']);
ClientDataSet1.InsertRecord([2, 'BDG']);
ClientDataSet1.InsertRecord([3, 'ADG']);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Adaptor.Free;
end;

Unable to insert Unicode into SQL Server 2008 using Delphi ZeosLib and Delphi 7

I'm having trouble inserting Unicode into a SQL Server database using Delphi ZeosLib and Delphi 7, and then reading the inserted value. I've created a simple test program that first inserts and then queries the inserted value.
The test table schema:
CREATE TABLE [dbo].[incominglog](
[message] [nvarchar](500) NULL
) ON [PRIMARY]
I've upload the simple test program source (ZeosLib source included) - click here to download. I've also included ntwdblib.dll but you can use your own.
The test program also requires TNT component which can be downloaded from here
Using the test program, the Unicode characters that I have inserted appear as question marks on retrieval - I'm not certain whether the problem lies with the insert code or the query code.
I've also tried encoding the data into utf-8 before inserting and then decoding the data after retrieving from utf-8 - please search "//inserted as utf8" in the test program source. I'm able to view the Unicode after it has been decoded, so this method works. However, for my actual application, I can't encode as UTF-8 as SQL Server doesn't support UTF-8 completely - some characters can't be stored. See my previous question here.
Will appreciate any pointers. :)
Meanwhile, here's the source for the Test program:
unit Unit1;
interface
uses
ZConnection, Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ZAbstractRODataset, ZAbstractDataset, ZAbstractTable, ZDataset,
StdCtrls, TntStdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
TntMemo1: TTntMemo;
Button2: TButton;
TntEdit1: TTntEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
FZConnection: TZConnection;
FZQuery: TZQuery;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
tntmemo1.Lines.Clear;
FZConnection := TZConnection.Create(Owner);
FZConnection.LoginPrompt := False;
FZQuery := TZQuery.Create(Owner);
FZQuery.Connection := FZConnection;
FZConnection.Protocol := 'mssql';
FZConnection.Database := 'replace-with-your-db';
FZConnection.HostName := 'localhost';
FZConnection.User := 'sa';
FZConnection.Password := 'replace-with-your-password';
FZConnection.Connect;
FZQuery.SQL.Text := 'SELECT * from incominglog';
FZQuery.ExecSQL;
FZQuery.Open;
FZQuery.First;
while not FZQuery.EOF do
begin
tntmemo1.Lines.add(FZQuery.FieldByName('message').AsString);
// tntmemo1.Lines.add(utf8decode(FZQuery.FieldByName('message').AsString)); //inserted as utf8
FZQuery.Next;
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
sqlstring, data:widestring;
begin
FZConnection := TZConnection.Create(Owner);
FZConnection.LoginPrompt := False;
FZQuery := TZQuery.Create(Owner);
FZQuery.Connection := FZConnection;
FZConnection.Protocol := 'mssql';
FZConnection.Database := 'replace-with-your-db';
FZConnection.HostName := 'localhost';
FZConnection.User := 'sa';
FZConnection.Password := 'replace-with-your-password';
FZConnection.Connect;
data:= tntedit1.Text;
// data:= utf8encode(tntedit1.Text); //inserted as utf8
sqlstring:= 'INSERT INTO INCOMINGLOG ([MESSAGE]) VALUES(N''' + data + ''')';
FZQuery.SQL.Text := sqlstring;
FZQuery.ExecSQL;
end;
end.
I have not tested your example, but I'm able to save and retrieve from database Unicode characters without problem on SQL Server with Delphi 7 VCL/CLX and zeoslib.
I think in your case it will be enough changing your save procedure like this :
procedure TForm1.Button2Click(Sender: TObject);
var
sqlstring : widestring;
data : UTF8String;
begin
FZConnection := TZConnection.Create(Owner);
FZConnection.LoginPrompt := False;
FZQuery := TZQuery.Create(Owner);
FZQuery.Connection := FZConnection;
FZConnection.Protocol := 'mssql';
FZConnection.Database := 'replace-with-your-db';
FZConnection.HostName := 'localhost';
FZConnection.User := 'sa';
FZConnection.Password := 'replace-with-your-password';
FZConnection.Connect;
data:= UTF8String( utf8encode(tntedit1.Text) );
sqlstring:= 'INSERT INTO INCOMINGLOG ([MESSAGE]) VALUES(:DATA)';
FZQuery.SQL.Text := sqlstring;
FZQuery.ParamByName('DATA').AsString := data;
FZQuery.ExecSQL;
end;
The point is changing your data string variable in UTF8String type, and use parameters pass the data string to the query ...
To be honest I use it with a ZTable and Post command, but it should be the same with a ZQuery like yours ...

Delphi ODBC Connection Dialog Component?

I am thinking about adding ODBC database connectivity to an application.
The user will at runtime configure and select their database odbc connection.
Are there any components that will give me the required series of dialogs ?
Allowing the user to select the data source type, select drivers, browse already
defined ODBC connections etc.
Cheers
Sam
You can try this, if you are using ADO components.
Option 1
Uses
OleDB,
ComObj,
ActiveX;
function Edit_ADO_ODBC_ConnectionString(ParentHandle: THandle; InitialString: WideString;out NewString: string): Boolean;
var
DataInit : IDataInitialize;
DBPrompt : IDBPromptInitialize;
DataSource: IUnknown;
InitStr : PWideChar;
begin
Result := False;
DataInit := CreateComObject(CLSID_DataLinks) as IDataInitialize;
if InitialString <> '' then
DataInit.GetDataSource(nil, CLSCTX_INPROC_SERVER, PWideChar(InitialString),IUnknown, DataSource);
DBPrompt := CreateComObject(CLSID_DataLinks) as IDBPromptInitialize;
{
DBPROMPTOPTIONS_WIZARDSHEET = $1;
DBPROMPTOPTIONS_PROPERTYSHEET = $2;
DBPROMPTOPTIONS_BROWSEONLY = $8;
DBPROMPTOPTIONS_DISABLE_PROVIDER_SELECTION = $10;
}
if Succeeded(DBPrompt.PromptDataSource(nil, ParentHandle,DBPROMPTOPTIONS_PROPERTYSHEET, 0, nil, nil, IUnknown, DataSource)) then
begin
InitStr := nil;
DataInit.GetInitializationString(DataSource, True, InitStr);
NewString := InitStr;
Result := True;
end;
end;
Result:=Edit_ADO_ODBC_ConnectionString(0,OldConnectionString,NewString);
Option 2
Uses
ADODB;
PromptDataSource(Self.Handle, InitialString);
Option 3
Uses
ADODB,
AdoConEd;
procedure TMainForm.Button2Click(Sender: TObject);
Var
ADOConnection1 : TADOConnection;
begin
ADOConnection1:=TADOConnection.Create(Self);
EditConnectionString(ADOConnection1);
end;
You must Select "Microsoft OLE DB Provider for ODBC Drivers"
Bye.
PromptDataSource Function from the ADODB unit. Two parameters are
required:
the calling form's handle
a connection string . If you want no default connection string
just pass an empty string as:
var sConn : WideString;
begin
sConn := PromptDataSource(Form1.Handle, '');
end;

Resources