{++++ GERMAN +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Im folgenden ein Beispiel, wie man alle Fremdschlüssel einer
Tabelle im MS SQL-Server 2000 auslesen kann.
Die gespeicherte Systemprocedure des SQL-Servers >> exec sp_fkeys [Tabellenname] <<
liefert ausschließlich die Schlüssel, die auf die gewählte Tabelle
zeigen.
Testen:
Unter BStartClick bei Aufruf der Procedure GetForeignKeys den Tabellenname
anpassen.
Anwendung erstellen, neue AdoConnection, AdoConnection.Name = ADOConnection1,
Verbindung zur Datenbank herstellen, neuer Button, Button.Name = BStart,
Neues Memo, Memo.Name = Memo1,
Doppelclick auf den Button.
Version:
Getestet unter Delphi 7(Ent) und WinXP
Weitergabe:
Diese Unit kann beliebig weitergegeben und verändert werden.
+++++ ENGLISH ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
The system stored procedure "sp_fkeys ([tablename])" will only give
a list of foreign key references to the given table.
The "GetForeignKeys" function above will give you the list of fields
that are "foreign hold" from other tables.
Try out: You'll need an AdoConnection to your DB ...
type TForm1 = class(TForm)
ADOConnection1: TADOConnection;
Memo1: TMemo;
BStart: TButton; procedure BStartClick(Sender: TObject); private
procedure GetForeignKeys(sTableName: string;
MyConnection: TADOConnection; var SlForeignKeyName,
SlKeysActTable,
SlKeysForeignTable,
SlForeignKeyTable: TStringList); public { Public-Deklarationen } end;
var Form1: TForm1;
implementation
{$R *.dfm}
(* Get foreign keys *) procedure TForm1.GetForeignKeys(sTableName: string;
MyConnection: TADOConnection; var SlForeignKeyName,
SlKeysActTable,
SlKeysForeignTable,
SlForeignKeyTable: TStringList); var MySelectQuery, MyRecordQuery: TADOQuery;
i: Integer;
SlKeysAct, SlKeysFor: TStringList;
sConstraintName, sForeignKeys, sForeignTable: string;
(* Schlüssel ermitteln *) procedure GetKeys(sKeyList: string; fAct: Boolean); var i: Integer;
sKey: string; begin i := 0; repeat Inc(i); if sKeyList[i] <> ',' then
begin sKey := sKey + sKeyList[i]; end
else
begin
if fAct then
begin SlKeysAct.Add(sKey); end
else
begin SlKeysFor.Add(sKey); end; if (Length(sKey) + 1) < i then
begin
if sKey[(i + 1)] = ' ' then
begin Inc(i); end; end;
sKey := ''; end; until (i = Length(sKeyList)); if sKey <> '' then
begin
if fAct then
begin SlKeysAct.Add(sKey); end
else
begin SlKeysFor.Add(sKey); end; end; end;
procedure GetForeignKeyFieldsAndTable(sSQL: string); var i: Integer;
sValue: string;
iPos: Integer;
fAddValue: Boolean;
fInFields: Boolean; begin
if Length(sSQL) >= 10 then
begin (* REFERENCES entfernen *) sValue := Copy(sSQL, 1, 10); if AnsiUpperCase(sValue) = 'REFERENCES' then
begin Delete(sSQL, 1, 11); end;
i := 0;
iPos := 0;
sValue := '';
fInFields := False; repeat Inc(i);
fAddValue := False; (* "normal" lesen *) if (sSQL[i] <> '.') and (sSQL[i] <> ' ') and (sSQL[i] <> '(') and (sSQL[i] <> ')') and (fInFields = False) then
begin sValue := sValue + sSQL[i];
fAddValue := True; end; (* In Felder *) if sSQL[i] = '(' then
begin fInFields := True; end; if (fInFields) and (sSQL[i] <> '(') and (sSQL[i] <> ')') then
begin sValue := sValue + sSQL[i]; end; (* Felder verlassen *) if sSQL[i] = ')' then
begin fInFields := False; end; if (fAddValue = False) and (fInFields = False) then
begin
case iPos of (* Datenbank *) 0: begin sValue := '';
Inc(iPos); end; (* Ower *) 1: begin sValue := '';
Inc(iPos); end; (* Tabelle *) 2: begin sForeignTable := sValue;
sValue := '';
Inc(iPos); end; (* Felder *) 3: begin sForeignKeys := sValue;
sValue := '';
Inc(iPos); end; else
begin
end; end; end; until (i = Length(sSQL)); end; end; begin
try MySelectQuery := TADOQuery.Create(Application); with MySelectQuery do
begin Name := 'MyHelpSelectQuery';
Connection := MyConnection;
SQL.Add('sp_help ' + sTableName);
Active := True; end; try MyRecordQuery := TADOQuery.Create(Application); with MySelectQuery do
begin Name := 'MyHelpRecordQuery';
Connection := MyConnection;
Recordset := MySelectQuery.NextRecordset(i);
Recordset := MySelectQuery.NextRecordset(i);
Recordset := MySelectQuery.NextRecordset(i);
Recordset := MySelectQuery.NextRecordset(i);
Recordset := MySelectQuery.NextRecordset(i); if MySelectQuery.State = dsBrowse then
begin Recordset := MySelectQuery.NextRecordset(i); if FindField('Constraint_Type') <> nil then
begin SlKeysAct := TStringList.Create;
SlKeysFor := TStringList.Create; try
while not EOF do
begin
if AnsiUpperCase(FieldByName('Constraint_Type').AsString) =
AnsiUpperCase('FOREIGN KEY') then
begin SlKeysAct.Clear; (* In einzelne Felder teilen *) GetKeys(FieldByName('Constraint_Keys').AsString, True); (* Constraint festhalten *) sConstraintName := FieldByName('Constraint_Name').AsString; (* Referenz steht im nächsten Datensatz *) Next; (* Tabelle und Felder auflösen *) GetForeignKeyFieldsAndTable(FieldByName('Constraint_Keys').AsString); (* In einzelne Felder teilen *) SlKeysFor.Clear;
GetKeys(sForeignKeys, False); for i := 0 to (SlKeysAct.Count - 1) do
begin SlForeignKeyName.Add(sConstraintName);