#sql #oracle #oracle10g
#sql #Oracle #oracle10g
Вопрос:
У меня есть таблица с чем-то вроде дюжины разных столбцов. Есть ли способ условно выбирать столбцы на основе определенного условия?
Например, мы скажем, что это таблица пользователя с именем пользователя, паролем и всем прочим и полем, которое содержит подсчет того, сколько раз этот пользователь не смог войти в систему. (Неправильный пароль, правильное имя пользователя). Таким образом, вместо запроса, который ничего не возвращает при неправильном имени пользователя или пароле, или запроса, который возвращает все, когда правильно только имя пользователя, я хотел бы запрос, который возвращает подмножество, когда имя пользователя правильное, но пароль неправильный.
Псевдо SQL:
SELECT column1,
column2,
column3,
column4,
column5,
column6,
--If this condition is not met the following columns are not selected
IF password = password
(
conditional_column1,
conditional_column2,
conditional_column3
)
FROM source_table
WHERE username = username
Я пробовал оператор CASE и DECODE, но каждый из них возвращает только одно значение для каждого условия. Я хочу выбрать несколько столбцов для одного условия.
У меня нет доступа к PL / SQL, и я пытаюсь сохранить все это в одном запросе. Кто-нибудь знает, возможно ли это?
Редактировать:
Просто чтобы уточнить, в моем случае я не хочу проверять, запрашиваю ли я имя пользователя, я хочу проверить, есть ли какие-либо строки, где username = x
. Если бы все, что мне нужно было сделать, это передать username
в функцию и создать строку запроса, это не было бы проблемой.
Итак, суть такова:
Получаем несколько столбцов, в которых имя пользователя равно ‘x’, затем, если пароль равен ‘y’, получаем эти другие столбцы.
Комментарии:
1. В чем проблема с возвратом дополнительных столбцов, а затем на прикладном уровне выбирается, какие из них отображать? Добавление столбцов в существующий результирующий набор не имеет значения в плане объяснения.
2. В моем конкретном случае я мог бы изменить один запрос или пять разных файлов кода. Я знаю, что это не идеальное решение, но оно удерживает меня от рефакторинга почти полудюжины файлов и скрещивания пальцев в надежде, что это не повлияет на что-то еще. Это унаследованный проект, и я действительно не драматизирую количество файлов, которые мне пришлось бы изменить.
3. Вы говорите, что у вас нет доступа к PL / SQL, но имеете ли вы в виду создание хранимых процедур? Если вы можете передать этот оператор select в виде строки в БД, то вы должны быть в состоянии передать анонимный блок с динамическим SQL в БД.
Ответ №1:
Похоже, вы хотите взглянуть на функцию виртуальной частной базы данных (VPD) oracle
Комментарии:
1. Сначала я подумал, о чем вы говорите, но это могло бы сработать, если его проблема действительно в пользовательском контроле.
2. Похоже, что это действительно сработает. Функция «скрытия столбцов» может быть именно тем, что мне нужно. Не знаю, есть ли у меня разрешения для VPD или я могу попросить ребят из базы данных настроить его.
3. Это Enterprise Edition, так что, надеюсь, вы уже платите за это. И я думаю, что он тоже использует PL / SQL, хотя, надеюсь, не тот, который вам запрещено использовать.
Ответ №2:
Джастин прав в том, что нет способа (кроме SELECT * или производных, таких как PIVOT) вернуть переменное количество столбцов из статического запроса. Мои 2 предложения:
-
Динамический SQL, если у вас есть контроль над тем, как создается запрос.
-
Определите максимальное количество столбцов и создайте представление поверх вашей source_table, используя CASE / DECODE, как вы уже пробовали. Вы можете добавить столбец индикатора для каждого условного столбца, если проверки null недостаточно. Я использовал это, чтобы успешно обойти проблему «не удается запросить неизвестный домен».
Ответ №3:
Когда запрос отправляется в механизм SQL, должно быть известно количество столбцов, которые будут выбраны. Механизм SQL не может допускать изменения количества столбцов во время выполнения.
Однако вы могли бы использовать динамический SQL для сборки запроса, который будет отправлен в механизм SQL динамически. Например, я могу создать процедуру PL / SQL, которая будет динамически собирать инструкцию SQL, включающую разные столбцы, и возвращать SYS_REFCURSOR
вызывающему объекту. Вы можете сделать нечто подобное на любом языке, который использует ваше приложение.
SQL> create or replace procedure dyn_emp( p_include_empno in boolean,
2 p_rc out sys_refcursor )
3 as
4 l_sql varchar2(1000);
5 begin
6 l_sql := 'SELECT ename ';
7 if( p_include_empno )
8 then
9 l_sql := l_sql || ', empno ';
10 end if;
11 l_sql := l_sql || ' from emp';
12 open p_rc for l_sql;
13 end;
14 /
Procedure created.
SQL> variable rc refcursor;
SQL> exec dyn_emp( true, :rc );
PL/SQL procedure successfully completed.
SQL> print rc
ENAME EMPNO
---------- ----------
SMITH 7369
ALLEN 7499
WARD 7521
JONES 7566
MARTIN 7654
BLAKE 7698
CLARK 7782
SCOTT 7788
KING 7839
TURNER 7844
ADAMS 7876
JAMES 7900
FORD 7902
MILLER 7934
14 rows selected.
SQL> exec dyn_emp( false, :rc );
PL/SQL procedure successfully completed.
SQL> print rc
ENAME
----------
SMITH
ALLEN
WARD
JONES
MARTIN
BLAKE
CLARK
SCOTT
KING
TURNER
ADAMS
JAMES
FORD
MILLER
14 rows selected.
Комментарии:
1. Это хорошая идея, но она не сработает. Как я уже упоминал, у меня нет доступа к PL / SQL, и выполнение этого на другом языке создало бы дополнительные запросы. Необходимые мне проверки условий зависят от информации в базе данных, имени пользователя или пароля, существующих в базе данных. Мне пришлось бы выполнить хотя бы один дополнительный вызов базы данных, чтобы проверить имя пользователя.