Неверный номер Oracle в предложении соединения

Попытка объяснить это более описательно,

Операция 1:

x = [[0, 0], [0, 0]]
print(type(x)) # <class 'list'>
print(x) # [[0, 0], [0, 0]]

x[0][0] = 1
print(x) # [[1, 0], [0, 0]]

Операция 2:

y = [[0] * 2] * 2
print(type(y)) # <class 'list'>
print(y) # [[0, 0], [0, 0]]

y[0][0] = 1
print(y) # [[1, 0], [1, 0]]

Заметил, почему не изменяется первый элемент первого списка не изменил второй элемент каждого списка? Это потому, что [0] * 2 действительно представляет собой список из двух чисел, и ссылка на 0 не может быть изменена.

Если вы хотите создать копии клонов, попробуйте выполнить операцию 3:

import copy
y = [0] * 2   
print(y)   # [0, 0]

y = [y, copy.deepcopy(y)]  
print(y) # [[0, 0], [0, 0]]

y[0][0] = 1
print(y) # [[1, 0], [0, 0]]

еще один интересный способ создания копий клонов, операция 4:

import copy
y = [0] * 2
print(y) # [0, 0]

y = [copy.deepcopy(y) for num in range(1,5)]
print(y) # [[0, 0], [0, 0], [0, 0], [0, 0]]

y[0][0] = 5
print(y) # [[5, 0], [0, 0], [0, 0], [0, 0]]
4
задан patrick3853 25 March 2019 в 08:27
поделиться

2 ответа

Я думаю, что самое простое решение использует case, который имеет больше гарантий порядка оценки:

SELECT a.*
FROM AGG_MATCHES m JOIN
     SOURCE_A a
     ON a.ID = (CASE WHEN m.AGGSRC = 'source_a' THEN TO_NUMBER(m.AGGPROJ_ID) END);

Или, еще лучше, преобразовать в строки:

SELECT a.*
FROM AGG_MATCHES m JOIN
     SOURCE_A a
     ON TO_CHAR(a.ID) = m.AGGPROJ_ID AND
        m.AGGSRC = 'source_a' ;

Тем не менее, лучший совет - это исправить модель данных.

Возможно, лучшим решением в вашем случае является просто представление или столбец генерации:

create view v_agg_matches_a as 
    select . . .,
           (case when regexp_like(AGGPROJ_ID, '^[0-9]+ 

case может не потребоваться, если вы используете представление, но это безопаснее.

Затем используйте представление в последующих запросах.

) then to_number(AGGPROJ_ID) end) as AGGPROJ_ID from agg_matches am where m.AGGSRC = 'source_a';

case может не потребоваться, если вы используете представление, но это безопаснее.

Затем используйте представление в последующих запросах.

0
ответ дан Gordon Linoff 25 March 2019 в 08:27
поделиться

Вы правы, что Oracle выполняет инструкцию в другом порядке, чем вы написали, что приводит к ошибкам преобразования.

Наилучшие способы решить эту проблему по порядку:

  1. Измените модель данных, чтобы всегда хранить данные как правильный тип. Всегда храните числа как числа, даты как даты и строки как строки. (Вы уже знаете это и сказали, что не можете изменить свою модель данных, это предупреждение для будущих читателей.)
  2. Преобразование чисел в строки с помощью TO_CHAR.
  3. Если вы используете 12.2, преобразуйте строки в числа, используя синтаксис DEFAULT return_value ON CONVERSION ERROR, например:

    SELECT *
    FROM (
        SELECT AGGPROJ_ID -- this column is a VARCHAR
        FROM AGG_MATCHES -- this is the table storing the matches
        WHERE AGGSRC = 'source_a'
    ) m
    JOIN SOURCE_A a ON a.ID = TO_NUMBER(m.AGGPROJ_ID default null on conversion error);
    
  4. Добавьте ROWNUM в строку чтобы предотвратить преобразования оптимизатора, которые могут переписать операторы. ROWNUM всегда оценивается в конце, и это заставляет Oracle запускать вещи в определенном порядке, даже если ROWNUM не используется. (Официально подсказки являются способом сделать это, но получить правильные подсказки слишком сложно.)

    SELECT *
    FROM (
        SELECT AGGPROJ_ID -- this column is a VARCHAR
        FROM AGG_MATCHES -- this is the table storing the matches
        WHERE AGGSRC = 'source_a'
            --Prevent optimizer transformations for type safety.
            AND ROWNUM >= 1
    ) m
    JOIN SOURCE_A a ON a.ID = TO_NUMBER(m.AGGPROJ_ID);
    
0
ответ дан Jon Heller 25 March 2019 в 08:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: