Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: #Table i magia...?

create procedure tmp_dropTemporary
as

create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

odpalam procedurę
Exec tmp_dropTemporary

w odpowiedzi mam:

(1 row(s) affected)

Server: Msg 207, Level 16, State 1, Procedure tmp_dropTemporary, Line 9
Invalid column name 'id_osoby'.

Ke, Why, dlaczego? :)

Odpalanie poza procedurą poszczególnych poleceń działa.
Odpalenie wszystkich razem - nie.
Siwieję...
Help.
Jacek Gużewski

Jacek Gużewski Architekt systemu

Temat: #Table i magia...?

Witam.

Jak pewnie wiesz tabela tymczasowa istnieje do czasu:
1. Zdropowanie - raczej rzadko się używa.
2. Do zakończenia danej sesji - najczęściej.

Przed uruchomieniem procedury sprawdź czy ta tabela istnieje i będziesz miała odpowiedź.
Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: #Table i magia...?

Tabelę tworzę jak widać wewnątrz procedury więc musi istnieć. W tej samej procedurze jest insert i drop.
Tabela jest widoczna przez całe trwanie procedury (znika po skończeniu działania proc) więc i drop powinien ją widzieć. (Tym bardziej, że sam drop - bez inserta wcześniejszego - działa).

Co więcej dopisanie w procedurze
select * into #TempTable2 from #TempTable
alter table #TempTable2 drop column id_osoby
Działa...

Dla mnie to mały koszmarek...
Na razie w ten sposób obejdę.
Gdyby jednak ktoś znał ładniejszy - działający sposób będę wdzięczna.
Robert Żwirski

Robert Żwirski programista, Black
Red White S.A.

Temat: #Table i magia...?

a moze zamiast "select * from #TempTable" napisz "select nazwisko from #TempTable" :)
Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: #Table i magia...?

:) Pisałam w innym wątku - to jest ta "dynamiczna tabela"
W oryginalnej - nie wiem ani ile, ani jakie nazwy mają kolumny :)
W przykładach to wygląda troszkę śmiesznie, ale chodzi o przedstawienie problemu :)
Boooo... hmmm... też pivot? O raju.. ale faktycznie będzie ładniej. :)

No pewnie że tak i ładnie i bez dodatkowych kursorów:)

Co nie zmienia istoty problemu (już tak dla podrążenia) czemu przedstawiony wcześniej problem się tak zachowuje (nie widzi kolumny... )

Z tego co udało mi się dowiedzieć (dziękuję Bartku), w trakcie kompilacji szeregowane są polecenia create, alter, insert, select.
Może procedura usuwa wcześniej kolumnę, do której później chce wstawić insertem?
Jednak nie zadziałało również zamknięcie dropa w oddzielnej procedurze odpalonej wewnętrznie (a to już chyba powinno zadziałać)

Pozostawiam do przemyślenia - nie dało się przeskoczyć, to obeszliśmy, ale jakby ktoś znał rozwiązanie - nie krępujcie się.Edyta Ratajczyk edytował(a) ten post dnia 06.12.07 o godzinie 12:05
Jacek Gużewski

Jacek Gużewski Architekt systemu

Temat: #Table i magia...?

Edyta Ratajczyk:
Tabelę tworzę jak widać wewnątrz procedury więc musi istnieć. W tej samej procedurze jest insert i drop.
Tabela jest widoczna przez całe trwanie procedury (znika po skończeniu działania proc) więc i drop powinien ją widzieć. (Tym bardziej, że sam drop - bez inserta wcześniejszego - działa).

Co więcej dopisanie w procedurze
select * into #TempTable2 from #TempTable
alter table #TempTable2 drop column id_osoby
Działa...

Dla mnie to mały koszmarek...
Na razie w ten sposób obejdę.
Gdyby jednak ktoś znał ładniejszy - działający sposób będę wdzięczna.

OK. Dla wyjaśnienia o co mi chodzi zrób tak:

1.Uruchom nową sesję query.
2. Uruchom skrypt (oczywiście jeśli jeszcze nie masz tego obiektu) :
create procedure tmp_dropTemporary
as

create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

3. Uruchom exec tmp_dropTemporary
4. Efekt powinien być taki, że wielkorotnie możesz uruchomić tą procedurę.
5. Uruchom jeden raz sktypt :
create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

6. Efekt pojedyńczego zwrócenia wartości.
7. Uruchom exec tmp_dropTemporary
8. Efekt - błąd jak opisałaś.

Komunikat który przedstawiłaś oznacza, że tabela jest już utworzona i kolumna jest już usunięta.
Jacek Gużewski

Jacek Gużewski Architekt systemu

Temat: #Table i magia...?

Edyta Ratajczyk:
Tabelę tworzę jak widać wewnątrz procedury więc musi istnieć. W tej samej procedurze jest insert i drop.
Tabela jest widoczna przez całe trwanie procedury (znika po skończeniu działania proc) więc i drop powinien ją widzieć. (Tym bardziej, że sam drop - bez inserta wcześniejszego - działa).

Co więcej dopisanie w procedurze
select * into #TempTable2 from #TempTable
alter table #TempTable2 drop column id_osoby
Działa...

Dla mnie to mały koszmarek...
Na razie w ten sposób obejdę.
Gdyby jednak ktoś znał ładniejszy - działający sposób będę wdzięczna.

OK. Dla wyjaśnienia o co mi chodzi zrób tak:

1.Uruchom nową sesję query.
2. Uruchom skrypt (oczywiście jeśli jeszcze nie masz tego obiektu) :
create procedure tmp_dropTemporary
as

create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

3. Uruchom exec tmp_dropTemporary
4. Efekt powinien być taki, że wielkorotnie możesz uruchomić tą procedurę.
5. Uruchom jeden raz sktypt :
create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

6. Efekt pojedyńczego zwrócenia wartości.
7. Uruchom exec tmp_dropTemporary
8. Efekt - błąd jak opisałaś.

Komunikat który przedstawiłaś oznacza, że tabela jest już utworzona i kolumna jest już usunięta.
Robert Żwirski

Robert Żwirski programista, Black
Red White S.A.

Temat: #Table i magia...?

Komunikat który przedstawiłaś oznacza, że tabela jest już utworzona i kolumna jest już usunięta.

ale w tymm wypadku komunikat powinien już wystąpić przy operacji "create table" . W sumie na końcu tej procedury mozna jeszcze dorzucic "drop table", tak dla pewności
Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: #Table i magia...?

Jako skrypt (nie procedura) też mi nie hula - taki sam komunikat - już też o tym napisałam.
Odpalenie poleceń po kolei - wszystko OK.

Drop w oryginalnej procedurze był, jak nie ma też hula - tabela #Temp powołana wewnątrz procedury istnieje wyłącznie do czasu jej zakończenia.

Najbardziej mi pasuje jednak, że kompilator procedury faktycznie szereguje polecenia i w efekcie procedura nie wykonuje się tak, jak mi się wydaje a tak (zaznaczona zamiana kolejności poleceń):

create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))

>>alter table #TempTable drop column id_osoby
>>insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
select * from #TempTable

Co po wywołaniu polecenia po poleceniu daje taki sam komunikat błędu (w tym przypadku mnie zupełnie nie dziwi) ;)
Robert Żwirski

Robert Żwirski programista, Black
Red White S.A.

Temat: #Table i magia...?

nie wiem czemu upierasz sie na "select *" , przeciez tworza tablicę #TempTable masz specyfikację kolumn, możesz potem uzyc je w selekcie
Jacek Gużewski

Jacek Gużewski Architekt systemu

Temat: #Table i magia...?

Robert Żwirski:
Komunikat który przedstawiłaś oznacza, że tabela jest już utworzona i kolumna jest już usunięta.

ale w tymm wypadku komunikat powinien już wystąpić przy operacji "create table" . W sumie na końcu tej procedury mozna jeszcze dorzucic "drop table", tak dla pewności

Nie tu jest pies pogrzebany. I na pewno nie ma tu znacznia kolejkowanie procedur w kompilatorze. Dla udowodnienia tego zróbcie taki skrypt:

create procedure tmp_dropTemporary1
as
create table #TempTable1(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable1 (id_osoby, nazwisko,imie) values (1,'ada','ada')
alter table #TempTable1 drop column id_osoby
select * from #TempTable1

Założenie takiej procedury wykona się prawidłowo. Zaś jej działanie niestety nie. Ilość pól w create jest inna niż w insert.
Kompilator, jeśli obiekt nie jest utworzony fizycznie w czasie kompilacji procedury, nie sprawdza poprawności obiektów, tylko poprawność składni. Jeśli zaś obiekt istnieje fizycznie w tej sesji, to dodatkowo sprawdza poprawność struktur. I stąd błąd :

Server: Msg 207, Level 16, State 1, Procedure tmp_dropTemporary, Line 9
Invalid column name 'id_osoby'.Jacek Gużewski edytował(a) ten post dnia 06.12.07 o godzinie 13:18
Mirosław Serwaczyński

Mirosław Serwaczyński Analityk programista

Temat: #Table i magia...?

Edyta Ratajczyk:
Najbardziej mi pasuje jednak, że kompilator procedury faktycznie
szereguje polecenia i w efekcie procedura nie wykonuje się tak,
jak mi się wydaje

I tu masz niestety rację - optymalizator tak robi, jest straszny cwaniak i nie da się oszukać :-)

Ale możesz to zrobić inaczej - rozbić działania na dwie procedury:
ALTER proc proc1
as
create table TempTable (id_osoby decimal(9),nazwisko nvarchar(100))
insert into TempTable (id_osoby, nazwisko) values (1,'ada')

ALTER proc proc2
as
alter table TempTable drop column id_osoby
select * from TempTable

ALTER proc proc3
as
exec proc1
exec proc2

W takim przypadku nasz cwaniak jest bezradny i wykona się OK - tyle że tabela przestała być tymczasowa
Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: #Table i magia...?

Jacek Gużewski:
Robert Żwirski:
Komunikat który przedstawiłaś oznacza, że tabela jest już utworzona i kolumna jest już usunięta.

ale w tymm wypadku komunikat powinien już wystąpić przy operacji "create table" . W sumie na końcu tej procedury mozna jeszcze dorzucic "drop table", tak dla pewności

Nie tu jest pies pogrzebany. I na pewno nie ma tu znacznia kolejkowanie procedur w kompilatorze. Dla udowodnienia tego zróbcie taki skrypt:

create procedure tmp_dropTemporary1
as
create table #TempTable1(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable1 (id_osoby, nazwisko,imie) values (1,'ada','ada')
alter table #TempTable1 drop column id_osoby
select * from #TempTable1

Założenie takiej procedury wykona się prawidłowo. Zaś jej działanie niestety nie. Ilość pól w create jest inna niż w insert.
Kompilator, jeśli obiekt nie jest utworzony fizycznie w czasie kompilacji procedury, nie sprawdza poprawności obiektów, tylko poprawność składni. Jeśli zaś obiekt istnieje fizycznie w tej sesji, to dodatkowo sprawdza poprawność struktur. I stąd błąd :

Server: Msg 207, Level 16, State 1, Procedure tmp_dropTemporary, Line 9
Invalid column name 'id_osoby'.Jacek Gużewski edytował(a) ten post dnia 06.12.07 o godzinie 13:18

Powtarzam. Polecenia z tej procedury odpalane pojedyńczo wykonywały się. Więc niby wsio ok. W Twoim przykładzie pojedyńczo też by się wyjechało, a komunikat jaki widzisz dotyczy nie kolumny imie, tylko wciąż id_osoba. :/
Tak więc Pozostaję przy moim. Kompilator/optymalizator przestawia... That's all. :)

PS. Czemu mam wrażenie, że piszemy o różnych rzeczach? ;)
Jacek Gużewski

Jacek Gużewski Architekt systemu

Temat: #Table i magia...?

Po pierwsze. Nie chcę wyjść na zarozumialca, ale się mylicie lub nie chcecie zrozumieć gdzie leży problem.
Po drugie. Postaram się dokładnie wytłumaczyć o co mi chodzi.
Po trzecie. Ostatni post, żeby nie wywoływac niepotrzebnych emocji.

Komunikat o treści:
" Server: Msg 207, Level 16, State 1, Procedure tmp_dropTemporary, Line 9 Invalid column name 'id_osoby'"
przy uruchomieniu skryptu:
"Exec tmp_dropTemporary"
który uruchamia procedurę utworzoną wcześniej o zawartości:
"create procedure tmp_dropTemporary
as
create table #TempTable(id_osoby decimal(9),nazwisko nvarchar 100))
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable"
informuje tylko i wyłącznie o tym, że obiekt #TempTable1 w bazie TEMPDB jest już utworzony i nie posiada pola id_osoby.
I problemem tu nie jest to że jest tam. Tylko to, że nie ma pola id_osoby. Ponieważ kompilator dla celów uruchomienia najpierw sprawdza popraność składni/struktury. NIE MA TY ZNACZENIA CZY ZMIENIA KOLEJNOŚĆ CZY NIE. A śmiem wątpić czy coś takiego robi, a przynajmniej nie wiem dlaczego miałby to robić.
Dlaczego sprawdza czy istnieje obiekt o takiej nazwie nie wiem. Ale tak robi, pomimo tego, że obiekt o nazwie #TempTable1 utworzony w procedurze i obiekt #TempTable1 utworzony bez niej są obsługiwane niezależnie. Dla udowodnienia wykonałem coś takiego:
W jednej sesji (jednym otwartym oknie z query) wykonuje następujące czynności:
1. Drop'uje procedure (jeśli istnije)
drop procedure tmp_dropTemporary
2. Dropuje tablice tymczasową (jeśli istnieje)
drop table #TempTable
3. Zakładam procedurę:
create procedure tmp_dropTemporary
as
create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

4. Wykonuję procedurę:
Exec tmp_dropTemporary
Otrzymuje jeden rekord z jednym polem
5. Uruchamiam skrypt:
create table #TempTable(id_osoby decimal(9),nazwisko nvarchar(100))
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
select * from #TempTable
Otrzymuje jeden rekord z dwoma polami
6. Wykonuję procedurę:
Exec tmp_dropTemporary
Otrzymuje jeden rekord z jednym polem
7. Wykonuje skrypt :
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
select * from #TempTable
Otrzymuje 2 rekordy z dwoma polami
8.Wykonuję procedurę:
Exec tmp_dropTemporary
Otrzymuje jeden rekord z jednym polem
9. Wykonuje skrypt :
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
select * from #TempTable
Otrzymuje 3 rekordy z dwoma polami.
10. Wykonuję procedurę:
Exec tmp_dropTemporary
Otrzymuje jeden rekord z jednym polem
11. Wykonuje skrypt :
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable
Otrzymuje 4 rekordy z jednym polem.
12. Wykonuję procedurę:
Exec tmp_dropTemporary
Otrzymuje błąd :
Msg 207, Level 16, State 1, Procedure tmp_dropTemporary, Line 6
Invalid column name 'id_osoby'.

Wniosek dla mnie jest taki:
W innym kontekście jest uruchamiane sprawdznie, a w innym wykonanie.
Życzę miłego dnia i powodzenia.
Przepraszam za nadgorliwość ale dla mnie ważniejsze jest rozwiązanie problemu niż eliminacja skutków problemów.
Edyta Ratajczyk

Edyta Ratajczyk
programista/bazodano
wiec/analityk
biznesowy IT

Temat: #Table i magia...?

:) Ja otwierałam wątek.
Jak byś nie zauważył - obeszłam problem, ale zacytuję samą siebie:
"Co nie zmienia istoty problemu (już tak dla podrążenia) czemu przedstawiony wcześniej problem się tak zachowuje (nie widzi kolumny... )"
Dobra, czepiam się, ale spokojnie, bez emocji (zwłaszcza niepotrzebnych)
A teraz odpowiedź właściwa.

Jacek Gużewski:
Po pierwsze. Nie chcę wyjść na zarozumialca, ale się mylicie W jednej sesji (jednym otwartym oknie z query) wykonuje następujące czynności:
1. Drop'uje procedure (jeśli istnije)
drop procedure tmp_dropTemporary
2. Dropuje tablice tymczasową (jeśli istnieje)
drop table #TempTable
3. Zakładam procedurę:
create procedure tmp_dropTemporary
as
create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

4. Wykonuję procedurę:
Exec tmp_dropTemporary
Otrzymuje jeden rekord z jednym polem

To się nie dogadamy. Bo u mnie już tu jest błąd.
Nie otrzymuję jednego rekordu z jednym polem. Przykrość.

Nie wiem, czy faktycznie zapuszczałeś to co napisałeś i działa, czy zgadujesz - bo wg mnie (na logikę) to też powinno działać, czy może to kwestia serwera (u mnie 2005). Zastanawia mnie, czemu w takim razie mimo utworzonej tabeli #Temp ze skryptu działa create z procedur - jeżeli z Twojego opisu wnioskuję, że tabela tworzona w procedurze (pkt 4, 6 ,8 ...) i tabela utworzona w sesji poza procedurą (pkt 5) to te same obiekty albo przynajmniej mocno związane (po usunięciu kolumny z tabeli "zewnętrznej" przestaje działać procedura).

Ja rozumiem o czym piszesz, jednak w moich próbach wykonania tego co napisałeś problemem jest to, że U MNIE NIE DZIAŁA TAK, JAK TY TO OPISAŁEŚ (może to tylko mój problem, jakieś ustawienia albo co?).
I próbuję dociec czemu.
Może ktoś inny rozsądzi. Wg mnie:
Tabele tworzone w procedurze są widoczne TYLKO wewnątrz niej (jakby otwierały kolejną sesję).
Po zakończeniu procedury znikają - przynajmniej u mnie, po procedurze nie ma śladu po tych tabelach - w odróżnieniu od skryptowych, które są widoczne do czasu zakończenia sesji.
Dlatego mimo utworzenia tabeli (pkt 5) można bez komunikatów o błędzie informującym, że taka tabela istnieje bezkarnie odpalać dowolną ilość razy procedurę...
Optymalizator jednak przestawia operacje (czemu - nie wiem).
Może to, że u Ciebie działa a u mnie nie - to kwestia ustawień systemowych albo co? Nie wiem...
Moja teoria jak to działa wg mnie już została przedstawiona.
Ponieważ u Ciebie działa a u mnie nie - nasza dalsza dysputa nie ma sensu.
Mirek i Robert zdają się rozumieć opisywany przeze mnie problem - być może mają takie same objawy :)

Pozdrawiam
Mirosław Serwaczyński

Mirosław Serwaczyński Analityk programista

Temat: #Table i magia...?

Jako żywo, testowałem w Query Analyzerze i widać, że MS-SQL ewidentnie zmienia kolejność instrukcji - alter table wykonuje się zaraz po create table, niezależnie od jego miejsca w kodzie, a insert dopiero potem.Mirosław Serwaczyński edytował(a) ten post dnia 07.12.07 o godzinie 08:30
Jacek Gużewski

Jacek Gużewski Architekt systemu

Temat: #Table i magia...?

Witam Państwa.
Ponieważ zacząłem wątpić w swoja inteligencję (bo jeśli chodzi o wiedzę, to nie ma podstaw żeby w nią nie wątpić - nauczyłem się pokory dla posiadanych przezemnie informacji) zadałem pytanie na forum MSSQL (WSS). Mam nadzieję, że poprawnie przedstawiłem problem.

http://www.wss.pl/frmThread.aspx?gid=17&tid=45480

Odpowiedzi udzieliła mi osoba, co do której nie mam żadnych wątpliwości co do wiedzy i praktyki. Sam chciałbym wiedzieć tyle o
SQL serwerze co On. Bardzo polecam ten portal.

Pozdrowienia.Jacek Gużewski edytował(a) ten post dnia 07.12.07 o godzinie 09:54
Bartosz Ratajczyk

Bartosz Ratajczyk MS SQL Developer

Temat: #Table i magia...?

Może jeszcze wróćmy do meritum, porzucając testy naokoło procedury. Sprawa jest prosta:

1) W MSSQL 2000 tworzę procedurę:
----------
create procedure tmp_dropTemporary
as

create table #TempTable(
id_osoby decimal(9),
nazwisko nvarchar(100))

insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable
----------
The command(s) completed successfully.

2) Uruchamiam procedurę:
----------
EXEC tmp_dropTemporary
----------
(1 row(s) affected)

(2 row(s) affected)

Server: Msg 207, Level 16, State 1, Procedure tmp_dropTemporary, Line 8
Invalid column name 'id_osoby'.

Pytanie zasadnicze: Dlaczego zgłasza błąd?
Jacek Gużewski

Jacek Gużewski Architekt systemu

Temat: #Table i magia...?

Witam.
I problem wynika z tego, że u mnie nie zwraca żadnego błędu. Ja to uruchamiam na SQL 2005.
Jest jeszcze jedna różnica: to to co jest wynikach
/
(1 row(s) affected)
nazwisko
---------------------------------
ada

(1 row(s) affected)
/

A robię dokładnie te sql'e co napisałeś w post'cie (kopiuj / wklej).
Mirosław Serwaczyński

Mirosław Serwaczyński Analityk programista

Temat: #Table i magia...?

Wstawiam do QueryAnalyzera (nie tworzę procedury):

create table #TempTable(id_osoby decimal(9),nazwisko nvarchar(100))
insert into #TempTable (id_osoby, nazwisko) values (1,'ada')
alter table #TempTable drop column id_osoby
select * from #TempTable

W MS-SQL2005 wykonuje się i zwraca rekord z jedną kolumną,

w MS-SQL2000 zwraca komunikat:

(1 row(s) affected)
Server: Msg 207, Level 16, State 1, Line 5
Invalid column name 'id_osoby'.

Widać więc różnicę albo w działaniu obu wersji, albo w ustawieniach jakiegoś (jakiego?!) parametru, różnie ustawianego domyślnie w obu wersjach.

Następna dyskusja:

uzupelnianie table of FK




Wyślij zaproszenie do