Попытка объяснить это более описательно,
Операция 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]]
Я думаю, что самое простое решение использует 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
может не потребоваться, если вы используете представление, но это безопаснее.
Затем используйте представление в последующих запросах.
Вы правы, что Oracle выполняет инструкцию в другом порядке, чем вы написали, что приводит к ошибкам преобразования.
Наилучшие способы решить эту проблему по порядку:
TO_CHAR
. Если вы используете 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);
Добавьте 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);