INSERT INTO @v
EXEC sp_tables
Evident ca INSERT INTO @variabila_tabela EXEC procedura conduce la obtinerea unei erori in SQL Server 2000 iar BOL 200 e foarte clara cu privire la acest tip de interogari ! Erori vei obtine daca vei incerca sa apelezi o functie/vedere DMF/DMV in SQL Server 2000 ! Sa mai zic ca - de exemplu - exista diferente (evidente) intre o versiune SQL Server non SP si una cu SP ? Si pentru ca tot a amintit xmldeveloper de sys.dm_... am sa enumer 2 vederi DMV care sunt disponibile incepand doar de la sp1: sys.dm_exec_query_memory_grants si sys.dm_exec_query_resource_semaphores.
TOP 1 diminueaza portabilitatea interogarii doar daca ea ar fi fost portabila [?] !
Pe mine ma intereseaza mai putin portabilitatea in lipsa unei cerinte EXPLICITE in acest sens. De regula, functionalitatile cele mai interesante sunt cele neportabile sau mai putin portabile. Intentia mea a fost aceea de a minimiza timpii suplimentati de procesare a clauzei DISTINCT. Evident ca in ceea ce priveste SQL Server si cele doua exemple care utilizeaza sp_tables si information_schema_tables se apeleaza function db_name().
Legat de portabilitate:
Intrebarea mea este la ce este util un standard daca nu-l respecta cei mai importanti jucatori din domeniu ? Plus ca nici MS nu respecta standardul (dintre multitudinea de exemple: vezi tipuri de date DATE, TIME din SQL 2008 :-) :-) :-), vezi TIMESTAMP :-) asta ca sa dau doar cateva exemple) ! Sa mai vorbim despre anumite comenzi, clauze, operatori ... din standardul SQL care sunt suportate de mai multi producatori dar comportamentul este DIFERIT desi sintaxa este identica (vezi LIKE in SQL Server / Oracle ... care este ba insenzitiv ba senzitiv implicit, ca sa dau doar un exemplu) ? Aceata interogare
SELECT * FROM tabela WHERE camp LIKE 'A%'
este in doar in aparenta portabila deoarece conduce la obtinerea unor rezultate diferite.
Si discutia poate continua ... ! Se pot scrie carti intregi cu privire la diferentele
dintre diferitele implementari ale pseudostandardelor SQL si cum se poate scrie cod SQL portabil. Si repet ce am spus mai sus: codul SQL portabil (DACA E PORTABIL) nu are nici un farmec.
Pentru ca tot a venit vorba de standarde, ce crezi ca va afisa Oracle sau/si MySql daca se incearca apelul urmator:
SELECT DISTINCT TABLE_CATALOG AS [Current Database] FROM INFORMATION_SCHEMA.TABLES
?
Cate o eroare.
Oracle: in primul rand identificatorul aliasului nu este recunoscut de Oracle ( ... AS [...] ) si in al doilea rand vederile din schema information_schema definita in standardul SQL nu sunt disponibile in Oracle.
MySql: de asemenea identificatorul aliasului nu este recunoscut de MySql. MySql recunoaste vederea information_schema.tables dar distractia abia acuma incepe pentru ca acel camp table_catalog (dupa care faci distinct in interogare) contine (conform documentatiei MySql 5) valori nule. Supriza ? Daca vb. de MySql nu nici o supriza. Au avut bug-uri si mai si ... (vezi cazul in care valorile 0 erau considerate null :-) :-) :-) ). Conform documentatie trebuie utilizat campul table_schema pentru a identifica tabela (tabela DA si nu schema; MySql e iarasi varza) de care apartine un obiect (tip tabela). Problema e ca MySql imi afiseaza in aceasta vedere obiecte la care am acces, din toate bazele de date (sunt conectat ca administrator) si nu doar acele obiectele din baza de date curenta la care utilizatorul este conectat asa cum procedeaza SQL Server. Standardul spune ca vederea tables trebuie sa permita vizualizarea tabelelor definite "in acest catalog" [tabele] care sunt accesibile utilizatorului. Se pare ca doar SQL Server (comparativ cu Oracle si MySql) are implementata vederea corect.
Totusi intrebarea este: unde e portabilitatea in acest caz ?
Daca s-ar fi solicitat din start o solutie pentru accesarea numelui bazei de date curenta orientata pe SQL Server / Oracle / MySql o solutie pe care as fi putut sa o indic ar fi fost:
CREATE VIEW MetadataDatabaseName
AS
SELECT DB_NAME() AS Name
respectiv
CREATE VIEW MetadataDatabaseName
AS
SELECT GLOBAL_NAME AS Name FROM GLOBAL_NAME
respectiv
CREATE VIEW MetadataDatabaseName
AS
SELECT DATABASE() Name
Vederea MetadataDatabaseName abstractizeaza denumirea bazei de date curente de tipul bazei de date (SQLServer/Oracle/MySql) a.i. interogarea
SELECT Name FROM MetadataDatabaseName
va fi portabila.
Intrebare intrebatoare:
De ce crezi ca Oracle si MySql afiseaza mesajul de eroare generat de identificatorul [Current Database] ?