01004 string data right truncation ๋?
01004 string data right truncation์ ๋ฌธ์์ด ๋ฐ์ดํฐ๋ฅผ ํน์ ๊ธธ์ด์ ์ปฌ๋ผ์ ์ฝ์
ํ๊ฑฐ๋ ์
๋ฐ์ดํธํ ๋, ์๋ณธ ๋ฐ์ดํฐ์ ๊ธธ์ด๊ฐ ๋์ ์ปฌ๋ผ์ ์ต๋ ํ์ฉ ๊ธธ์ด๋ฅผ ์ด๊ณผํ์ฌ ๋ท๋ถ๋ถ์ด ์๋ ค๋๊ฐ๋ ์ํฉ์์ ๋ฐ์ํ๋ ๊ฒฝ๊ณ (Warning) ์ฝ๋์
๋๋ค. ์๋ฐํ ๋งํ๋ฉด ์๋ฌ๊ฐ ์๋ ๊ฒฝ๊ณ (SQLSTATE 01004)๋ก ๋ถ๋ฅ๋์ง๋ง, ๋๋ผ์ด๋ฒ๋ ORM์ ๋ฐ๋ผ ์์ธ๋ก ์ฒ๋ฆฌ๋์ด ์ ํ๋ฆฌ์ผ์ด์
์ฅ์ ๋ฅผ ์ ๋ฐํ ์ ์์ต๋๋ค. ํนํ CHAR(n), VARCHAR(n) ํ์
์ ์ปฌ๋ผ์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ ๋ ์์ฃผ ๋ฐ์ํ๋ฉฐ, ๋ฐ์ดํฐ ๋ฌด๊ฒฐ์ฑ ๋ฌธ์ ๋ก ์ด์ด์ง ์ ์์ด ๋ฐ๋์ ์ฃผ์ํด์ผ ํฉ๋๋ค.
์ฃผ์ ๋ฐ์ ์์ธ
1. ์ปฌ๋ผ ๊ธธ์ด๋ณด๋ค ๊ธด ๋ฌธ์์ด ์ง์ ์ฝ์
๊ฐ์ฅ ํํ ์์ธ์ผ๋ก, VARCHAR(50)์ผ๋ก ์ ์๋ ์ปฌ๋ผ์ 50์๋ฅผ ์ด๊ณผํ๋ ๋ฌธ์์ด์ INSERT ๋๋ UPDATEํ ๋ ๋ฐ์ํฉ๋๋ค. ํนํ ์ธ๋ถ API ์๋ต๊ฐ, ์ฌ์ฉ์ ์
๋ ฅ๊ฐ, ํน์ ๋ ๊ฑฐ์ ์์คํ
์์ ๋ง์ด๊ทธ๋ ์ด์
๋ ๋ฐ์ดํฐ๊ฐ ์์๋ณด๋ค ๊ธด ๊ฒฝ์ฐ ์ด ๋ฌธ์ ๊ฐ ๋น๋ฒํ๊ฒ ๋ํ๋ฉ๋๋ค.
2. ์คํค๋ง ๋ณ๊ฒฝ ์์ด ๋ฐ์ดํฐ ์๊ตฌ์ฌํญ์ด ๋ณํํ ๊ฒฝ์ฐ
์๋น์ค ์ด๊ธฐ์๋ VARCHAR(20)์ผ๋ก ์ถฉ๋ถํ๋ ์ฃผ์, ์ด๋ฆ, ์ํ๋ช
๋ฑ์ ์ปฌ๋ผ์ด ์๊ฐ์ด ์ง๋จ์ ๋ฐ๋ผ ๋ ๊ธด ๋ฐ์ดํฐ๋ฅผ ์์ฉํด์ผ ํ๋ ์ํฉ์ด ๋ฉ๋๋ค. ๊ฐ๋ฐ์๊ฐ ์ ํ๋ฆฌ์ผ์ด์
๋ก์ง์ ์์ ํ์ง๋ง DB ์คํค๋ง ๋ณ๊ฒฝ์ ๋๋ฝํ๋ฉด ์ด ๊ฒฝ๊ณ ๊ฐ ์ง์์ ์ผ๋ก ๋ฐ์ํ๋ฉฐ, ์๋ฆฐ ๋ฐ์ดํฐ๊ฐ ์ค์ DB์ ์ ์ฅ๋๋ ์ฌ๊ฐํ ๊ฒฐ๊ณผ๋ฅผ ์ด๋ํ ์ ์์ต๋๋ค.
3. ๋ฌธ์ ์ธ์ฝ๋ฉ ์ฐจ์ด๋ก ์ธํ ๋ฐ์ดํธ ๊ธธ์ด ์ด๊ณผ
PostgreSQL์์ VARCHAR(n)์ n์ ๋ฌธ์(character) ์๋ฅผ ์๋ฏธํ์ง๋ง, JDBC๋ ODBC ๋๋ผ์ด๋ฒ์์ ๋ด๋ถ์ ์ผ๋ก ๋ฐ์ดํธ ๊ธฐ์ค์ผ๋ก ๊ธธ์ด๋ฅผ ๊ณ์ฐํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. UTF-8 ํ๊ฒฝ์์ ํ๊ธ, ์ผ๋ณธ์ด, ์ค๊ตญ์ด ๋ฑ ๋ฉํฐ๋ฐ์ดํธ ๋ฌธ์๋ ํ ๊ธ์๊ฐ 3๋ฐ์ดํธ๋ฅผ ์ฐจ์งํ๋ฏ๋ก, ๋๋ผ์ด๋ฒ ๋ ๋ฒจ์์ ๊ธธ์ด ์ด๊ณผ๋ก ์๋ชป ํ๋จํ๊ฑฐ๋ ์ค์ ๋ก ๋ฐ์ดํธ ์ ํ์ ๊ฑธ๋ฆฌ๋ ์ํฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
ํด๊ฒฐ ๋ฐฉ๋ฒ
์์ธ 1 ํด๊ฒฐ: ์ฝ์ ์ ๋ฌธ์์ด ๊ธธ์ด ๊ฒ์ฆ ๋ฐ ๋ช ์์ ํธ๋ฆฌ๋ฐ
๋ฐ์ดํฐ ์ฝ์
์ ์ ๊ธธ์ด๋ฅผ ๋ฏธ๋ฆฌ ํ์ธํ๊ฑฐ๋, LEFT() ๋๋ SUBSTRING() ํจ์๋ก ๋ช
์์ ์ผ๋ก ์๋ผ์ ๋ฃ๋ ๋ฐฉ๋ฒ์
๋๋ค. ๋ค๋ง ์ด ๋ฐฉ๋ฒ์ ๋ฐ์ดํฐ ์์ค์ ๊ฐ์ํ๋ ๊ฒ์ด๋ฏ๋ก, ๋น์ฆ๋์ค ๋ก์ง์ ํ์ฉ๋๋์ง ๋ฐ๋์ ๊ฒํ ํด์ผ ํฉ๋๋ค.
-- ๋ฌธ์ ๊ฐ ๋๋ ์ํฉ ์ฌํ
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(10) NOT NULL
);
-- 10์ ์ด๊ณผ ๋ฐ์ดํฐ ์ฝ์
์๋
INSERT INTO users (username) VALUES ('์ด๊ฒ์์ด๊ธ์๋ฅผ์ด๊ณผํ๋์ฌ์ฉ์์ด๋ฆ์
๋๋ค');
-- ERROR: value too long for type character varying(10)
-- ํด๊ฒฐ 1: ์ฝ์
์ ๊ธธ์ด ํ์ธ
SELECT LENGTH('์ด๊ฒ์์ด๊ธ์๋ฅผ์ด๊ณผํ๋์ฌ์ฉ์์ด๋ฆ์
๋๋ค'); -- ๋ฌธ์ ์ ๋ฐํ
-- ํด๊ฒฐ 2: LEFT()๋ก ๋ช
์์ ์ ์ญ ํ ์ฝ์
(๋ฐ์ดํฐ ์์ค ๊ฐ์)
INSERT INTO users (username)
VALUES (LEFT('์ด๊ฒ์์ด๊ธ์๋ฅผ์ด๊ณผํ๋์ฌ์ฉ์์ด๋ฆ์
๋๋ค', 10));
-- ํด๊ฒฐ 3: CASE ๊ตฌ๋ฌธ์ผ๋ก ์กฐ๊ฑด ๋ถ๊ธฐ
INSERT INTO users (username)
SELECT
CASE
WHEN LENGTH(username_input) > 10
THEN SUBSTRING(username_input FROM 1 FOR 10)
ELSE username_input
END
FROM (SELECT '์ด๊ฒ์์ด๊ธ์๋ฅผ์ด๊ณผํ๋์ฌ์ฉ์์ด๋ฆ์
๋๋ค' AS username_input) t;
์์ธ 2 ํด๊ฒฐ: ์ปฌ๋ผ ํ์ ๊ธธ์ด ํ์ฅ
๊ทผ๋ณธ์ ์ธ ํด๊ฒฐ์ฑ
์ ์ปฌ๋ผ์ ์ต๋ ๊ธธ์ด๋ฅผ ๋๋ฆฌ๋ ๊ฒ์
๋๋ค. PostgreSQL์์๋ VARCHAR ๊ธธ์ด๋ฅผ ๋๋ฆฌ๋ ์์
์ ํ
์ด๋ธ ์ฌ์์ฑ ์์ด ์ฆ์ ์ฒ๋ฆฌ๋๋ฏ๋ก ์ด์ ์ค์ธ ์๋น์ค์ ํฐ ์ํฅ ์์ด ์ ์ฉํ ์ ์์ต๋๋ค.
-- ํ์ฌ ์ปฌ๋ผ ์ ์ ํ์ธ
SELECT
column_name,
data_type,
character_maximum_length
FROM information_schema.columns
WHERE table_name = 'users'
AND column_name = 'username';
-- VARCHAR ๊ธธ์ด ํ์ฅ (PostgreSQL์์๋ ๊ธธ์ด ์ฆ๊ฐ๋ ํ
์ด๋ธ ๋ฝ ์์ด ์ฆ์ ๋ฐ์)
ALTER TABLE users
ALTER COLUMN username TYPE VARCHAR(100);
-- ๊ธธ์ด ์ ํ์ด ์ฌ์ค์ ๋ถํ์ํ ๊ฒฝ์ฐ TEXT ํ์
์ผ๋ก ๋ณ๊ฒฝ (๊ถ์ฅ)
ALTER TABLE users
ALTER COLUMN username TYPE TEXT;
-- ๋ณ๊ฒฝ ํ ํ์ธ
\d users
์ค๋ฌด ํ: ๊ฐ๋ณ ๊ธธ์ด ๋ฌธ์์ด์๋
VARCHAR(n)๋์TEXTํ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค. PostgreSQL์์TEXT์VARCHAR๋ ๋ด๋ถ์ ์ผ๋ก ๋์ผํ๊ฒ ์ฒ๋ฆฌ๋๋ฉฐ,TEXT๋ ๊ธธ์ด ์ ํ์ด ์์ด ๋ถํ์ํ ํธ๋ฐ์ผ์ด์ ๋ฌธ์ ๋ฅผ ์ฌ์ ์ ๋ฐฉ์งํฉ๋๋ค.
์์ธ 3 ํด๊ฒฐ: ์ธ์ฝ๋ฉ ๋ฌธ์ ์ง๋จ ๋ฐ ๋ฐ์ดํธ ๊ธธ์ด ๊ธฐ์ค ์ฒ๋ฆฌ
-- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ธ์ฝ๋ฉ ํ์ธ
SHOW server_encoding;
SELECT pg_encoding_to_char(encoding) FROM pg_database WHERE datname = current_database();
-- ๋ฌธ์ ์ vs ๋ฐ์ดํธ ์ ๋น๊ต ํ์ธ
SELECT
'ํ๊ธํ
์คํธ' AS sample_text,
LENGTH('ํ๊ธํ
์คํธ') AS char_length, -- ๋ฌธ์ ์: 5
OCTET_LENGTH('ํ๊ธํ
์คํธ') AS byte_length; -- ๋ฐ์ดํธ ์: 15 (UTF-8 ๊ธฐ์ค)
-- ๋ฐ์ดํธ ๊ธฐ์ค์ผ๋ก ๊ธธ์ด๋ฅผ ์ ํํด์ผ ํ๋ ๊ฒฝ์ฐ
-- (์ธ๋ถ ์์คํ
๊ณผ ์ฐ๋ ์ ๋ฐ์ดํธ ์ ํ์ด ์์ ๋)
SELECT
input_text,
SUBSTRING(input_text FROM 1 FOR
-- ๋ฐ์ดํธ 30 ์ด๋ด์์ ์ต๋ํ ๋ง์ ๋ฌธ์ ํฌํจ
LENGTH(CONVERT_TO(input_text, 'UTF8')::text)
) AS safe_text
FROM (SELECT 'ํ๊ธ์ดํฌํจ๋๊ธด๋ฌธ์์ด๋ฐ์ดํฐ์
๋๋ค' AS input_text) t;
-- pg_column_size๋ก ์ค์ ์ ์ฅ ํฌ๊ธฐ ํ์ธ
SELECT pg_column_size('ํ๊ธํ
์คํธ'::text) AS storage_size;
์๋ฐฉ ๋ฐฉ๋ฒ
1. ์ปฌ๋ผ ํ์ ์ค๊ณ ์ TEXT ์ฐ์ ์์น๊ณผ CHECK ์ ์ฝ ์กฐ๊ฑด ํ์ฉ
์ด๊ธฐ ์คํค๋ง ์ค๊ณ ๋จ๊ณ์์ ๊ธธ์ด ์ ํ์ด ๋น์ฆ๋์ค ๊ท์น์ ๋ช
ํํ ํ์ํ ๊ฒฝ์ฐ(์: ์ฐํธ๋ฒํธ๋ ์ ํํ 5์๋ฆฌ)๊ฐ ์๋๋ผ๋ฉด TEXT ํ์
์ ๊ธฐ๋ณธ์ผ๋ก ์ฌ์ฉํ๊ณ , ๊ธธ์ด ์ ํ์ CHECK ์ ์ฝ ์กฐ๊ฑด์ผ๋ก ๋ช
์์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ ๋ฒจ์์ ์๋ฌ ๋ฉ์์ง๊ฐ ๋ ๋ช
ํํด์ง๊ณ , ์ ์ฝ ์กฐ๊ฑด๋ง ์์ ํ๋ฉด ๋๋ฏ๋ก ์ ์ง๋ณด์์ฑ์ด ๋์์ง๋๋ค.
-- ๊ถ์ฅํ๋ ์ปฌ๋ผ ์ค๊ณ ํจํด
CREATE TABLE products (
id SERIAL PRIMARY KEY,
product_code TEXT NOT NULL,
product_name TEXT NOT NULL,
description TEXT,
-- ๋น์ฆ๋์ค ๊ท์น์ด ์๋ ๊ฒฝ์ฐ์๋ง CHECK ์ ์ฝ ์กฐ๊ฑด ์ฌ์ฉ
CONSTRAINT chk_product_code_length CHECK (LENGTH(product_code) <= 20),
CONSTRAINT chk_product_name_length CHECK (LENGTH(product_name) <= 200)
);
-- ๊ธธ์ด ์ ํ ๋ณ๊ฒฝ ์ CHECK ์ ์ฝ ์กฐ๊ฑด๋ง ์์ ํ๋ฉด ๋จ
ALTER TABLE products
DROP CONSTRAINT chk_product_name_length;
ALTER TABLE products
ADD CONSTRAINT chk_product_name_length CHECK (LENGTH(product_name) <= 500);
2. ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ์ ๊ธธ์ด ๊ฒ์ฆ ๋ก์ง ๋ด์ฌํ
ETL ์์
, ๋ฐฐ์น ์ฒ๋ฆฌ, API ์ฐ๋ ๋ฑ ์ธ๋ถ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๋ ๋ชจ๋ ํ์ดํ๋ผ์ธ์ ์ฌ์ ๊ฒ์ฆ ์ฟผ๋ฆฌ๋ฅผ ์ถ๊ฐํฉ๋๋ค. ์ด์ ํ๊ฒฝ์ ๋ฐ์ํ๊ธฐ ์ , ์คํ
์ด์ง ํ๊ฒฝ์์ ์ค์ ๋ฐ์ดํฐ๋ก ๊ธธ์ด ์ด๊ณผ ์ฌ๋ถ๋ฅผ ํญ์ ์ ๊ฒํ๋ ์ต๊ด์ ํ ์ฐจ์์์ ์ ์ฐฉ์ํค๋ ๊ฒ์ด ์ค์ํฉ๋๋ค.
-- ๋ง์ด๊ทธ๋ ์ด์
๋๋ ๋๋ ์ ์ฌ ์ ์ฌ์ ๊ฒ์ฆ ์ฟผ๋ฆฌ
-- ๊ฐ ์ปฌ๋ผ์ ์ต๋ ๊ธธ์ด๋ฅผ ์ปฌ๋ผ ์ ์์ ๋น๊ต
SELECT
'username' AS column_name,
MAX(LENGTH(username)) AS max_data_length,
10 AS column_limit,
COUNT(CASE WHEN LENGTH(username) > 10 THEN 1 END) AS violation_count
FROM staging_users
UNION ALL
SELECT
'email' AS column_name,
MAX(LENGTH(email)) AS max_data_length,
255 AS column_limit,
COUNT(CASE WHEN LENGTH(email) > 255 THEN 1 END) AS violation_count
FROM staging_users;
-- ์๋ฐ ๋ฐ์ดํฐ ์์ธ ์กฐํ
SELECT id, username, LENGTH(username) AS len
FROM staging_users
WHERE LENGTH(username) > 10
ORDER BY len DESC
LIMIT 20;
๊ด๋ จ ์๋ฌ
22001(string_data_right_truncation):01004์ ์๋ฌ ๋ฒ์ ์ผ๋ก, ๊ฒฝ๊ณ ๊ฐ ์๋ ์ค์ ์๋ฌ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค. PostgreSQL์์VARCHAR(n)์ด๊ณผ ์ฝ์ ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ด ์๋ฌ ์ฝ๋๊ฐ ๋ฐ์ํ๋ฉฐ,"value too long for type character varying(n)"๋ฉ์์ง์ ํจ๊ป ํธ๋์ญ์ ์ด ๋กค๋ฐฑ๋ฉ๋๋ค.22007(invalid_datetime_format): ๋ฌธ์์ด์ ๋ ์ง/์๊ฐ ํ์ ์ผ๋ก ๋ณํํ ๋ ํ์์ด ๋ง์ง ์์ ๋ฐ์ํ๋ ์๋ฌ๋ก, ๋ฌธ์์ด ๋ฐ์ดํฐ ํ์ ๋ถ์ผ์น ๋ฌธ์ ์ ์ฐ์ฅ์ ์ ์์ต๋๋ค.42804(datatype_mismatch): ์ปฌ๋ผ ํ์ ๊ณผ ์ฝ์ ํ๋ ค๋ ๋ฐ์ดํฐ ํ์ ์ด ์์ ํ ๋ค๋ฅผ ๋ ๋ฐ์ํ๋ฉฐ, ๋ฌธ์์ด ๊ด๋ จ ์คํค๋ง ์ค๊ณ ์ค๋ฅ์์ ํจ๊ป ๋ํ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ต๋๋ค.22P02(invalid_text_representation): ๋ฌธ์์ด์ ๋ค๋ฅธ ํ์ (์: INTEGER, UUID ๋ฑ)์ผ๋ก ์บ์คํ ํ ๋ ๋ณํ ๋ถ๊ฐ๋ฅํ ํ์์ด๋ฉด ๋ฐ์ํ๋ฉฐ, ํ์ ๋ณํ ๊ด๋ จ ์ค๋ฅ ๋๋ฒ๊น ์ ํจ๊ป ํ์ธํด์ผ ํฉ๋๋ค.










