J'utilise Oracle et j'ai une très grande table. Je dois vérifier l'existence d'une ligne de remplacement de quelques critères simples. Quelle est la meilleure façon d'aller à ce sujet à l'aide de SQL simple?
Voici ma meilleure hypothèse, et bien que cela puisse s'avérer assez rapide à mes besoins, j'aimerais apprendre une manière canonique pour faire fondamentalement SQL Server's "Existe "En oracle: p> le nombre () serait alors retourné comme un booléen dans un autre niveau. Le point principal est que je veux que Oracle fasse le strict minimum pour cette requête - j'ai seulement besoin de savoir s'il y a des lignes correspondant aux critères. P> et oui, ces colonnes seront très indexées. < / p> p>
4 Réponses :
DECLARE ex INT; BEGIN BEGIN SELECT NULL INTO ex FROM dual WHERE 1 = 1 AND rownum = 1; DBMS_OUTPUT.put_line('found'); EXCEPTION WHEN no_data_found THEN DBMS_OUTPUT.put_line('not found'); END; END;
Peut-être même un indice de premier_Rows? Optimizer devrait faire cela implicitement quand il voit le rownum = 1 Je pense. Sélectionnez / * + First_Rows (N) * / NULL
@ROBERT: Bien sûr que cela ne fera pas mal d'en ajouter un, mais cela ne fonctionne vraiment que dans des jointures (il rend l'optimiseur à préférer la boucle imbriquée sur Hash Rejoinks)
@Quassnoi: Je pensais que cela rend l'optimiseur 'Index Happy' aussi.
@ROBERT: Les index sont bons pour la boucle imbriquée mais pas toujours bonne pour les jointures de hasch. Dans ce sens, oui, le prémunt_rows utilise des boucles imbriquées qui utilisent à son tour des index. Mais pour une seule table de table, l'indice sera utilisé quand même: il n'ya aucun avantage d'utiliser un FullScan ici et l'optimiseur ne le considérera pas probablement même à moins que ce soit explicitement dit.
Le Rownum = 1 est suffisant pour que l'optimisateur choisisse un plan qui trouvera la première rangée dès que possible.
Pourquoi pas seulement utiliser existe-t-il? Oracle fera l'optimisation de Rownum = 1 pour vous.
Vous avez besoin d'une requête SELECT. Vous ne pouvez pas simplement utiliser si vous n'existe pas dans SQL Server
Utilisation de Count (*) est ok si vous utilisez également ROWNUM = 1:
declare l_cnt integer; begin select count(*) into l_cnt from x where x.col_a = value_a and x.col_b = value_b and rownum = 1; end;
@Tony - feriez-vous un compte (*) au lieu d'un existant? Pour moi, une existe semble plus naturelle, même si vous avez besoin de faire face à l'exception.
Voulez-vous dire "Select 1 de Dual où existe-t-il (...)"? Je ne le ferais pas, mais peut comprendre pourquoi certains le feraient. Ce qui est vraiment voulu être très naturel est une construction PL / SQL comme "si existe-t-il (sélectionnez ...) alors ..."!
Je suis paresseux ici en ne le testant pas moi-même, mais ne compterais pas (x_id) être plus rapide que le compte (), ou est-ce que l'interprétation SQL est suffisamment intelligente pour voir qu'il n'a pas vraiment besoin de se développer " / I> "?
Le nombre (*) est optimisé pour être aussi efficace que toute autre méthode.
FWIW: Expliquer le plan pour cela n'a montré aucune différence de coût entre le nombre (*) et Rownum = 1 contre l'approche existante pour un exemple simple.
begin select 'row DOES exist' into ls_result from dual where exists (select null from x where x.col_a = value_a and x.col_b = value_b); exception when no_data_found then ls_result := ' row does NOT exist'; end;
Je pense que l'utilisation d'Exist donne une réponse plus naturelle à la question que d'essayer d'optimiser une requête de comptage en utilisant Rownum.
Laissez Oracle faire l'optimisation de Rownum pour vous. P>
create or replace function is_exists ( p_value_a varchar2, p_value_b varchar2) return boolean is v_exists varchar2(1 char); begin begin select 'Y' into v_exists from dual where exists (select 1 from x where x.col_a = p_value_a and x.col_b = p_value_a); exception when no_data_found then v_exists := null; end; return v_exists is not null; end is_exists;