답변:
나는 비슷한 문제를 겪고 있었지만 함수의 오버 헤드를 원하지 않았다. 나는 다음과 같은 쿼리를 생각해 냈다.
SELECT myfield::integer FROM mytable WHERE myfield ~ E'^\\d+$';
Postgres는 조건부 바로 가기를 사용하므로 정수가 아닌 정수를 적중하지 않아야합니다. 또한 NULL 값을 처리합니다 (정규 표현식과 일치하지 않습니다).
선택하지 않고 0을 원하면 CASE 문이 작동합니다.
SELECT CASE WHEN myfield~E'^\\d+$' THEN myfield::integer ELSE 0 END FROM mytable;
E'\\d{1,5}$'
.
{1,5}
오버플로가 걱정된다면 @Bobort의 자릿수 제한은 좋은 아이디어 일 수 있지만 더 큰 숫자를 가리면 테이블을 변환 할 때 문제가 발생할 수 있습니다. 개인적으로 쿼리 오류가 먼저 발생하고 내 "정수"중 일부가 문제가 있음을 알고 싶습니다 ( E'\\d{6,}$'
먼저 선택하여 선택할 수도 있음 ).
예외 블록을 사용할 수 있는 자체 변환 함수를 만들 수도 있습니다 .
CREATE OR REPLACE FUNCTION convert_to_integer(v_input text)
RETURNS INTEGER AS $$
DECLARE v_int_value INTEGER DEFAULT NULL;
BEGIN
BEGIN
v_int_value := v_input::INTEGER;
EXCEPTION WHEN OTHERS THEN
RAISE NOTICE 'Invalid integer value: "%". Returning NULL.', v_input;
RETURN NULL;
END;
RETURN v_int_value;
END;
$$ LANGUAGE plpgsql;
테스트 :
=# select convert_to_integer('1234');
convert_to_integer
--------------------
1234
(1 row)
=# select convert_to_integer('');
NOTICE: Invalid integer value: "". Returning NULL.
convert_to_integer
--------------------
(1 row)
=# select convert_to_integer('chicken');
NOTICE: Invalid integer value: "chicken". Returning NULL.
convert_to_integer
--------------------
(1 row)
INSERT
합니까?
나는 같은 종류의 요구가 있었고 이것이 나를 위해 잘 작동한다는 것을 알았습니다 (postgres 8.4).
CAST((COALESCE(myfield,'0')) AS INTEGER)
시연 할 몇 가지 테스트 사례 :
db=> select CAST((COALESCE(NULL,'0')) AS INTEGER);
int4
------
0
(1 row)
db=> select CAST((COALESCE('','0')) AS INTEGER);
int4
------
0
(1 row)
db=> select CAST((COALESCE('4','0')) AS INTEGER);
int4
------
4
(1 row)
db=> select CAST((COALESCE('bad','0')) AS INTEGER);
ERROR: invalid input syntax for integer: "bad"
필드에 숫자가 아닌 텍스트 (예 : "100bad")가있을 가능성을 처리해야하는 경우 regexp_replace를 사용하여 캐스트 전에 숫자가 아닌 문자를 제거 할 수 있습니다.
CAST(REGEXP_REPLACE(COALESCE(myfield,'0'), '[^0-9]+', '', 'g') AS INTEGER)
그런 다음 "b3ad5"와 같은 text / varchar 값도 숫자를 제공합니다
db=> select CAST(REGEXP_REPLACE(COALESCE('b3ad5','0'), '[^0-9]+', '', 'g') AS INTEGER);
regexp_replace
----------------
35
(1 row)
Chris Cogdon이 "bad"(숫자 없음)와 같은 경우를 포함하여 모든 경우에 0을 제공하지 않는 솔루션에 대한 우려를 해결하기 위해 다음과 같이 조정했습니다.
CAST((COALESCE(NULLIF(REGEXP_REPLACE(myfield, '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
변환 할 값이 숫자가 아닌 문자 (예 : "bad") 인 경우 0을 제공한다는 점을 제외하고는 더 간단한 솔루션과 유사하게 작동합니다.
db=> select CAST((COALESCE(NULLIF(REGEXP_REPLACE('no longer bad!', '[^0-9]+', '', 'g'), ''), '0')) AS INTEGER);
coalesce
----------
0
(1 row)
이것은 다소 해킹 일 수 있지만 우리의 경우에는 작업이 완료되었습니다.
(0 || myfield)::integer
설명 (Postgres 8.4에서 테스트) :
위에서 언급 한 표현식은 빈 문자열의 NULL
NULL 값 myfield
과 0
빈 문자열에 대해 산출 합니다 (이 정확한 동작은 사용 사례에 맞거나 맞지 않을 수 있음).
SELECT id, (0 || values)::integer from test_table ORDER BY id
테스트 데이터 :
CREATE TABLE test_table
(
id integer NOT NULL,
description character varying,
"values" character varying,
CONSTRAINT id PRIMARY KEY (id)
)
-- Insert Test Data
INSERT INTO test_table VALUES (1, 'null', NULL);
INSERT INTO test_table VALUES (2, 'empty string', '');
INSERT INTO test_table VALUES (3, 'one', '1');
쿼리 결과는 다음과 같습니다.
---------------------
|1|null |NULL|
|2|empty string|0 |
|3|one |1 |
---------------------
선택 만하면 values::integer
오류 메시지가 나타납니다.
도움이 되었기를 바랍니다.
SELECT CASE WHEN myfield="" THEN 0 ELSE myfield::integer END FROM mytable
PostgreSQL로 작업 한 적이 없지만 SELECT 쿼리에서 IF 구문의 올바른 구문에 대해 매뉴얼 을 확인했습니다 .
@Matthew의 답변 이 좋습니다. 그러나 더 간단하고 빠를 수 있습니다. 그리고 질문은 빈 문자열 ( ''
) 을로 변환 0
하지만 다른 "유효하지 않은 입력 구문"또는 "범위를 벗어난"입력은 변환 하지 않습니다.
CREATE OR REPLACE FUNCTION convert_to_int(text)
RETURNS int AS
$func$
BEGIN
IF $1 = '' THEN -- special case for empty string like requested
RETURN 0;
ELSE
RETURN $1::int;
END IF;
EXCEPTION WHEN OTHERS THEN
RETURN NULL; -- NULL for other invalid input
END
$func$ LANGUAGE plpgsql IMMUTABLE;
0
빈 문자열과 NULL
유효하지 않은 다른 입력을 반환 합니다 . 모든 데이터 유형 변환에
쉽게 적용 할 수 있습니다 .
예외 블록을 입력하면 비용이 훨씬 많이 듭니다. 빈 문자열이 일반적인 경우 예외를 발생시키기 전에 해당 사례를 파악하는 것이 좋습니다.
빈 문자열이 매우 드문 경우 테스트를 예외 절로 옮기는 데 비용이 듭니다.
CREATE OR REPLACE FUNCTION parse_int(s TEXT) RETURNS INT AS $$
BEGIN
RETURN regexp_replace(('0' || s), '[^\d]', '', 'g')::INT;
END;
$$ LANGUAGE plpgsql;
0
입력 문자열에 숫자가 없으면 이 함수는 항상 반환 합니다.
SELECT parse_int('test12_3test');
돌아올 것이다 123
다음 코드가 쉽고 작동한다는 것을 알았습니다. 원래 답변은 여기 https://www.postgresql.org/message-id/371F1510.F86C876B@sferacarta.com
prova=> create table test(t text, i integer);
CREATE
prova=> insert into test values('123',123);
INSERT 64579 1
prova=> select cast(i as text),cast(t as int)from test;
text|int4
----+----
123| 123
(1 row)
그것이 도움이되기를 바랍니다
SUBSTRING은 경우에 따라 도움이 될 수 있습니다. int의 크기를 제한 할 수 있습니다.
SELECT CAST(SUBSTRING('X12312333333333', '([\d]{1,9})') AS integer);
데이터가 정수 여야하고 정수로만 필요한 값이라면, 전체 마일리지로 이동하여 열을 정수 열로 변환하지 않겠습니까?
그런 다음 데이터가 테이블에 삽입되는 시스템 지점에서 잘못된 값을 0으로 한 번만 변환 할 수 있습니다.
위의 변환을 사용하면 Postgres가 해당 테이블에 대한 각 쿼리의 각 단일 행에 대해 해당 값을 반복해서 변환해야합니다.이 테이블 의이 열에 대해 많은 쿼리를 수행하면 성능이 크게 저하 될 수 있습니다.
다음 기능은
error_result
캐스팅 할 수없는 결과에 대해 기본값 ( )을 사용하십시오. abc
또는999999999999999999999999999999999999999999
null
로null
bigints
은 다음과 비교 lower_bound
됩니다. 예 : 양수 값만 적용CREATE OR REPLACE FUNCTION cast_to_bigint(text)
RETURNS BIGINT AS $$
DECLARE big_int_value BIGINT DEFAULT NULL;
DECLARE error_result BIGINT DEFAULT -1;
DECLARE lower_bound BIGINT DEFAULT 0;
BEGIN
BEGIN
big_int_value := CASE WHEN $1 IS NOT NULL THEN GREATEST(TRIM($1)::BIGINT, lower_bound) END;
EXCEPTION WHEN OTHERS THEN
big_int_value := error_result;
END;
RETURN big_int_value;
END;