[dbf - MS SQL] Zapytanie z DBF do MSSQL w Delphi

0

Witam,
Pracuję w Delphi.
W programie łączę się z dwoma bazami danych i chcę przenosić część danych z jednej bazy do drugiej.
Bazą źródłową - tą na której wykonywany jest SELECT jest zwykła baza "dbf", natomiast INSERT jest wykonywany do bazy MSSQL.
I mam w związku z tym pytanie: jak można najlepiej i najwydajniej takie "przeniesienie" danych wykonać.
Czy można to zrobić w jednym zapytaniu tzn. INSERT do bazy MSSQL wraz z podzapytaniem (SELECTEM z bazy dbf).

INSERT INTO table_MSSQL (col1, col2) SELECT col1, col2 FROM table_DBF

Jeżeli tak się nie da, to jak mógłbym wykonać to "przeniesienie"? Za pośrednictwem pliku, czy też przez jakąś zmienną tablicową?

Proszę o pomoc bardziej doświadczonych... :)

0

Można to zrobić z poziomu bazy MSSQL przy użyciu jedynie SSMS.

INSERT INTO dbo.TabelaMSSQL (pole1, pole2, pole3)
SELECT pole1, pole2, pole3
FROM OPENROWSET(
'MSDASQL',
'Driver={Microsoft dBASE Driver (*.dbf)};DBQ=C:\',
'SELECT * FROM TabelaDBF')

gdzie 'TabelaMSSQL' to nazwa tabeli w bazie MSSQL, 'TabelaDBF' to nazwa pliku dbf, a 'C:' to lokalizacja pliku DBF

0

Dziękuję, ale chodziło mi bardziej o rozwiązanie zastosowane w aplikacji (opartej w moim przypadku na środowisku Delphi), która pozwoli na wykonywanie tych czynności cyklicznie w sposób przyjazny dla użytkownika...

0

Czy coś stoi na przeszkodzie, bo ja nie widzę takiego problemu.

0

Ja niestety jeszcze borykam się z tym problemem w Delphi.

Używam komponentu ADOConnection dla połączenia z bazą MSSQL.

Mam zdefiniowaną procedurę wykonywania zapytań:

procedure zapytanie(zapytanie:string;ADOQuery:TADOQuery);
begin
    ADOQuery.Close;
    ADOQuery.SQL.Clear;
    ADOQuery.SQL.Add(zapytanie);
    ADOQuery.ExecSQL;
end;

I problem z samym zapytaniem:
zapytanie('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET('MSDASQL','Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\DBF\','SELECT * FROM tabela_DBF');',ADOQuery1);

W wyniku otrzymuję komunikat o treści iż polecenie to nie posiada wystarczających parametrów...

0

Zwróciłeś uwagę, że masz w zapytaniu kilka apostrofów? Jak myślisz skąd kompilator ma widzieć gdzie zapytanie się zaczyna, a gdzie kończy jeżeli nawet TY sam tego nie wiesz?

0

Otóż znam długość zapytania, tylko nie mam jeszcze doświadczenia w programowaniu w Delphi, stąd trochę gubię się jeszcze w tej materii i szukam pomocy na forum.
Prosząc więc o wyrozumiałość i cierpliwość chciałbym jeszcze poprosić o dalszą pomoc, albowiem w tym momencie program już się uruchamia, jednak przy próbie wykonania zapytania INSERT otrzymuje komunikat o błędzie: "Niepoprawnie zdefiniowany obiekt Parametr. Podano niespójne lub niepełne informacje."
Wiec znów gdzieś w tym zapytaniu popełniłem błąd.. [???]
Na chwilę obecną owo zapytanie wygląda tak:

zapytanie('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET(MSDASQL,Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\DBF\,SELECT * FROM tabela_DBF);',ADOQuery1);

0

To co było w apostrofach ma pozostać w apostrofach, bo inaczej nie zadziała. Musisz tylko przekazać kompilatorowi, że kolejne apostrofy są dalszą częścią zapytania i nie oznaczają jego końca.

Innymi słowy chcesz wiedzieć jak użyć apostrof w stringu. Odpowiedź już wiele razy padła na tym forum, wystarczy poszukać w dziale Delphi/Pascal.

0

ogolnie pomocna jest funkcja QuotedStr('Jakies zapytanie np ala ma ''kota'' ')

0

Mam w dalszym ciągu problem z tym tematem...
Próbowałem już wielu kombinacji i dalej nie przynosi to pożądanych rezultatów. M.in.:

zapytanie(QuotedStr('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET('MSDASQL.1','Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\DBF\','SELECT * FROM tabela_DBF');'),ADOQuery1);

zapytanie(QuotedStr('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET('MSDASQL.1','Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\\DBF\\','SELECT * FROM tabela_DBF');'),ADOQuery1);

zapytanie(QuotedStr('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET("MSDASQL.1","Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\\DBF\\","SELECT * FROM tabela_DBF");'),ADOQuery1);

zapytanie('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET("MSDASQL.1","Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\\DBF\\","SELECT * FROM tabela_DBF");',ADOQuery1);

zapytanie(QuotedStr('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET(''MSDASQL.1'',''Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\DBF\'',''SELECT * FROM tabela_DBF'');'),ADOQuery1);

Przepraszam, ale po prost nie mogę sobie z tym poradzić.

0

IMHO nie musisz korzystać z QuotedStr, a zapytanie powinno zadziałać jeżeli przed każdym apostrofem zawartym w treści zapytania postawisz drugi apostrof, czyli:
zapytanie('INSERT INTO tabela_MSSQL (pole1, pole2) SELECT pole1, pole2 FROM OPENROWSET(''MSDASQL.1'',''Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\DBF\'',''SELECT * FROM tabela_DBF'');',ADOQuery1);

Jeżeli będziesz miał kolejne problemy to precyzyjnie określ jakie i jakie błędy zwraca kompilator albo MSSQL. Poza tym warto byłoby najpierw przetestować te zapytanie w SQL Server Managment Studio czy w ogóle działa, zwraca to co trzeba itp i dopiero wtedy implementować to w Delphi.

0

Chciałbym bardzo podziękować za pomoc, gdyż była to dla mnie dość skomplikowana kwestia :)

Na ten moment pozostał mi jedynie problem polskich znaków. Tzn. importują się do bazy "znaczki" zamiast polskich ogonków...
Czy jest na to jakaś rada?

Poza tym mam jeszcze jedno pytanie związane z ograniczeniem długości zapytania do 255 znaków.
Mam dość długie zapytanie i do dej pory radziłem sobie w taki sposób iż łączyłem je znakiem "+" np.: 'zapytanie_cz1'+'zapytanie_cz2'+'zapytanie_cz3' itd...
Jednak w moim problematycznym przykładzie po OPENROWSET to co się znajduje w nawiasie nie da się tak połączyć w taki sposób.
Chciałbym więc dopytać jeszcze jak można podzielić część zapytania występującą w nawiasach po OPENROWSET w moim zapytaniu.

0

Czy mógłbym liczyć na pomoc?

0

Oba pytania bardziej mają związek z Delphi niż z samą bazą danych. Myślę, że jak zadasz te pytania na forum Delphi to szybciej uzyskasz odpowiedź.

0
AdamPL napisał(a)

Można to zrobić z poziomu bazy MSSQL przy użyciu jedynie SSMS.

INSERT INTO dbo.TabelaMSSQL (pole1, pole2, pole3)
SELECT pole1, pole2, pole3
FROM OPENROWSET(
'MSDASQL',
'Driver={Microsoft dBASE Driver (*.dbf)};DBQ=C:\',
'SELECT * FROM TabelaDBF')

gdzie 'TabelaMSSQL' to nazwa tabeli w bazie MSSQL, 'TabelaDBF' to nazwa pliku dbf, a 'C:' to lokalizacja pliku DBF

Ten kod jest bardzo przydatny jednak to on zamienia wszystkie polskie znaki w nieczytelne krzaczki. Ma ktoś pomysł jak temu zaradzić?

0
INSERT INTO tabela_MSSQL (pole1, pole2) SELECT nazwa FROM OPENROWSET
('MSDASQL','Driver={Microsoft dBASE Driver (*.dbf)};DBQ=D:\DBF\',
'SELECT * FROM tabela_DBF') 

Teraz powinno działać. Brakuje kilku ' i ostatniego nawiasu.

w C++ robię to tak:

AnsiString zapytanie1="INSERT INTO...";
Form2->ADOQuery1->SQL->Clear();
Form2->ADOQuery1->SQL->Add(zapytanie);
Form2->ADOQuery1->ExecSQL();
Form2->ADOQuery1->Active=true;
0

Być może lepiej użyć jakiegoś narzędzia do przenoszenia danych typu DataPump? Nastąpi automatyczne dobranie konwersji typów, przeniesienie indeksów i szybciej wszystko pójdzie, przy dużej bazie.

0

W przypadku kłopotów z kodowaniem wystarczy ustawić CODEPAGE: http://msdn.microsoft.com/en-us/library/ms190312.aspx

1 użytkowników online, w tym zalogowanych: 0, gości: 1