Хорошим местом для начала является JavaDocs . Они охватывают это:
Брошено, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:
- Вызов метода экземпляра нулевого объекта.
- Доступ или изменение поля нулевого объекта.
- Выполнение длины null, как если бы это был массив.
- Доступ или изменение слотов с нулевым значением, как если бы это был массив.
- Бросать нуль, как если бы это было значение Throwable.
Приложения должны бросать экземпляры этого класса для указания других незаконных видов использования нулевого объекта.
Также, если вы попытаетесь использовать нулевую ссылку с
synchronized
, который также выдаст это исключение, за JLS :SynchronizedStatement: synchronized ( Expression ) Block
- В противном случае, если значение выражения равно null,
NullPointerException
.Как это исправить?
Итак, у вас есть
NullPointerException
. Как вы это исправите? Возьмем простой пример, который выдаетNullPointerException
:public class Printer { private String name; public void setName(String name) { this.name = name; } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer(); printer.print(); } }
Идентифицирует нулевые значения
. Первый шаг - точно определить , значения которого вызывают исключение . Для этого нам нужно выполнить некоторую отладку. Важно научиться читать stacktrace . Это покажет вам, где было выбрано исключение:
Exception in thread "main" java.lang.NullPointerException at Printer.printString(Printer.java:13) at Printer.print(Printer.java:9) at Printer.main(Printer.java:19)
Здесь мы видим, что исключение выбрано в строке 13 (в методе
printString
). Посмотрите на строку и проверьте, какие значения равны нулю, добавив протоколирующие операторы или используя отладчик . Мы обнаруживаем, чтоs
имеет значение null, а вызов методаlength
на него вызывает исключение. Мы видим, что программа перестает бросать исключение, когдаs.length()
удаляется из метода.Трассировка, где эти значения взяты из
Затем проверьте, откуда это значение. Следуя вызовам метода, мы видим, что
s
передается сprintString(name)
в методеprint()
, аthis.name
- null.Трассировка, где эти значения должны быть установлены
Где установлен
this.name
? В методеsetName(String)
. С некоторой дополнительной отладкой мы видим, что этот метод вообще не вызывается. Если этот метод был вызван, обязательно проверьте порядок , что эти методы вызывают, а метод set не будет называться после методом печати. Этого достаточно, чтобы дать нам решение: добавить вызов
printer.setName()
перед вызовомprinter.print()
.Другие исправления
Переменная может иметь значение по умолчанию (и
setName
может помешать ему установить значение null):private String name = "";
Либо метод
printString
может проверить значение null например:printString((name == null) ? "" : name);
Или вы можете создать класс, чтобы
name
всегда имел ненулевое значение :public class Printer { private final String name; public Printer(String name) { this.name = Objects.requireNonNull(name); } public void print() { printString(name); } private void printString(String s) { System.out.println(s + " (" + s.length() + ")"); } public static void main(String[] args) { Printer printer = new Printer("123"); printer.print(); } }
См. также:
Я все еще не могу найти проблему
Если вы попытались отладить проблему и до сих пор не имеете решения, вы можете отправить вопрос для получения дополнительной справки, но не забудьте включить то, что вы пробовали до сих пор. Как минимум, включите stacktrace в вопрос и отметьте важные номера строк в коде. Также попробуйте сначала упростить код (см. SSCCE ).
С предложением модели SQL:
SQL> select pid
2 , ltrim(sentence) sentence
3 from ( select pid
4 , seq
5 , sentence
6 from b
7 model
8 partition by (pid)
9 dimension by (seq)
10 measures (descr,cast(null as varchar2(100)) as sentence)
11 ( sentence[any] order by seq desc
12 = descr[cv()] || ' ' || sentence[cv()+1]
13 )
14 )
15 where seq = 1
16 /
P SENTENCE
- ---------------------------------------------------------------------------
A Have a nice day
B Nice Work.
C Yes we can do this work!
3 rows selected.
Я написал об этом здесь . И если вы перейдете по ссылке на поток OTN, вы найдете еще несколько примеров, включая сравнение производительности.
Аналитическая функция LISTAGG была введена в Oracle 11g Release 2 , что упрощает агрегацию строк. Если вы используете 11g Release 2, вы должны использовать эту функцию для агрегации строк. Пожалуйста, обратитесь к url для получения дополнительной информации о конкатенации строк.
http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php
В выборе, где вы хотите выполнить конкатенацию, вызовите функцию SQL.
Например:
select PID, dbo.MyConcat(PID)
from TableA;
Затем для функции SQL:
Function MyConcat(@PID varchar(10))
returns varchar(1000)
as
begin
declare @x varchar(1000);
select @x = isnull(@x +',', @x, @x +',') + Desc
from TableB
where PID = @PID;
return @x;
end
Синтаксис заголовка функции может быть неправильным, но принцип работает.
Я использую LISTAGG, но возвращаю эту строку для персидской строки!
мой запрос:
SELECT
listagg(DESCRIPTION,' , ') within group (order by DESCRIPTION)
FROM
B_CEREMONY
результат:
'A7'1 , ,4F
Пожалуйста, помогите мне .
wow это решение работает:
SELECT listagg(convert(DESCRIPTION, 'UTF8', 'AL16UTF16'),' , ') within group
(order by DESCRIPTION)
FROM B_CEREMONY;
11g и выше: используйте listagg :
SELECT
col1,
LISTAGG(col2, ', ') WITHIN GROUP (ORDER BY col2) "names"
FROM table_x
GROUP BY col1
10g и ниже: один из методов заключается в использовании функции:
CREATE OR REPLACE FUNCTION get_comma_separated_value (input_val in number)
RETURN VARCHAR2
IS
return_text VARCHAR2(10000) := NULL;
BEGIN
FOR x IN (SELECT col2 FROM table_name WHERE col1 = input_val) LOOP
return_text := return_text || ',' || x.col2 ;
END LOOP;
RETURN LTRIM(return_text, ',');
END;
/
To используйте функцию:
select col1, get_comma_separated_value(col1) from table_name
Примечание. В некоторых более старых версиях Oracle есть (неподдерживаемая) функция WM_CONCAT
, которая может вам помочь - см. здесь для деталей .
В MySQL:
SELECT col1, GROUP_CONCAT(col2) FROM table_name GROUP BY col1
Для тех, кто должен решить эту проблему с помощью Oracle 9i (или ранее), вам, вероятно, придется использовать SYS_CONNECT_BY_PATH, так как LISTAGG недоступен.
Чтобы ответить на OP, следующий запрос отобразит PID из таблицы A и объединить все столбцы DESC из таблицы B:
SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
FROM (
SELECT a.pid, seq, description
FROM table_a a, table_b b
WHERE a.pid = b.pid(+)
)
)
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;
Также могут быть экземпляры, в которых ключи и значения содержатся в одной таблице. Следующий запрос может использоваться там, где нет таблицы A, и существует только таблица B:
SELECT pid, SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
SELECT ROW_NUMBER () OVER (PARTITION BY pid ORDER BY pid, seq) rnum, pid, description
FROM (
SELECT pid, seq, description
FROM table_b
)
)
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1 AND PRIOR pid = pid
GROUP BY pid
ORDER BY pid;
Все значения могут быть переупорядочены по желанию. Отдельные конкатенированные описания могут быть переупорядочены в предложении PARTITION BY, и список PID может быть переупорядочен в конечном предложении ORDER BY.
Альтернативно: могут быть моменты, когда вы хотите объединить все значения из целой таблицы в одну строку.
Ключевая идея здесь заключается в использовании искусственного значения для группы описаний, которые будут конкатенированы.
В следующем запросе константа string ' 1 ', но любое значение будет работать:
SELECT SUBSTR (MAX (SYS_CONNECT_BY_PATH (description, ', ')), 3) all_descriptions
FROM (
SELECT ROW_NUMBER () OVER (PARTITION BY unique_id ORDER BY pid, seq) rnum, description
FROM (
SELECT '1' unique_id, b.pid, b.seq, b.description
FROM table_b b
)
)
START WITH rnum = 1
CONNECT BY PRIOR rnum = rnum - 1;
Индивидуальные конкатенированные описания могут быть переупорядочены в предложении PARTITION BY.
Несколько других ответов на этой странице также упомянули об этом чрезвычайно полезная ссылка: https://oracle-base.com/articles/misc/string-aggregation-techniques
Как видно из большинства ответов, LISTAGG
является очевидным вариантом. Однако один раздражающий аспект с LISTAGG
заключается в том, что если общая длина конкатенированной строки превышает 4000 символов (предел для VARCHAR2
в SQL), то возникает ошибка ниже, которую трудно управлять в версиях Oracle до 12.1
ORA-01489: результат конкатенации строки слишком длинный
blockquote>Новая функция, добавленная в 12cR2, является предложением
ON OVERFLOW
вLISTAGG
. Запрос, включающий это предложение, будет выглядеть так:SELECT pid, LISTAGG(Desc, ' ' on overflow truncate) WITHIN GROUP (ORDER BY seq) AS desc FROM B GROUP BY pid;
Вышеуказанное ограничивает вывод до 4000 символов, но не будет вызывать ошибку
ORA-01489
.Это некоторые из дополнительные опции
ON OVERFLOW
:
ON OVERFLOW TRUNCATE 'Contd..'
: в конце строки отобразится'Contd..'
(по умолчанию...
)ON OVERFLOW TRUNCATE ''
: Это будет отображать 4000 символов без какой-либо завершающей строки.ON OVERFLOW TRUNCATE WITH COUNT
: отобразится общее количество символов в конце после завершающих символов. Например: -...(5512)
'ON OVERFLOW ERROR
: Если вы ожидаете, чтоLISTAGG
потерпит неудачу с ошибкойORA-01489
(которая по умолчанию по умолчанию).
Попробуйте этот код:
SELECT XMLAGG(XMLELEMENT(E,fieldname||',')).EXTRACT('//text()') "FieldNames"
FROM FIELD_MASTER
WHERE FIELD_ID > 10 AND FIELD_AREA != 'NEBRASKA';
SELECT pid, LISTAGG(Desc, ' ') WITHIN GROUP (ORDER BY seq) AS description
FROM B GROUP BY pid;
SELECT pid, TO_STRING(CAST(COLLECT(Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
SELECT pid, TO_STRING(CAST(COLLECT(Desc ORDER BY Desc) AS varchar2_ntt)) AS Vals FROM B GROUP BY pid;
Все остальные методы были медленнее.
Или функция Oracle STRAGG (column).
Я должен сказать, что этот вид обработки очень ограничен ... если вы превысите ширину поля или ширину экрана ...
Прежде чем запускать запрос выбора, запустите это:
SET SERVEROUT ON SIZE 6000
SELECT XMLAGG(XMLELEMENT(E,SUPLR_SUPLR_ID||',')).EXTRACT('//text()') "SUPPLIER"
FROM SUPPLIERS;
Существует также функция XMLAGG
, которая работает с версиями до 11.2. Поскольку WM_CONCAT
является недокументированным и не поддерживается Oracle , рекомендуется не использовать его в производственной системе.
С помощью XMLAGG
вы можете сделать следующее:
SELECT XMLAGG(XMLELEMENT(E,ename||',')).EXTRACT('//text()') "Result"
FROM employee_names
Что это значит,
ename
(объединенные запятой) из таблицы employee_names
в элемент xml (с тегом E)