앞에서 날짜,시간 형식 type에 대해 알아보았고, 이어서 날짜,시간 함수 활용법에 대하여 알아보고자 한다.

우선 기본적으로 현재 시간(DB기준)을 확인하는 함수는 아래와 같다.

 
select now();
--출력결과(예시) : 2023-01-25 05:29:19.793694+00
 
 
주요함수로 date_part() 가 있는데 해당 함수를 이용해서 날짜 or 시간값에서 연도, 월, 주등과 같은 정보를 검색 할 수 있다.
추가로 extract() 함수도 존재하나 흡사한 방식으로 사용가능하다. (참고)
 
[ 필요인자 ]
 
인자값 정의
CENTURY 1세기는 서기 0001-01-01 00:00:00 시작되지만 당시에는 몰랐습니다. 정의는 모든 그레고리오력 국가에 적용됩니다. 세기 숫자 0 없으며 -1 세기에서 1 세기로 이동합니다. 이에 동의하지 않는 경우 다음 주소로 불만 사항을 작성하십시오: 교황, 로마 베드로 대성당, 바티칸.
DAY 값의 경우 일(월) 필드(1–31) ; 값의 경우 일 수timestampinterval
DECADE 연도 필드를 10으로 나눈
DOW 일요일(0)에서 토요일(6)
DOY 연도의 날짜(1–365/366)
EPOCH 값의 경우 1970-01-01 00:00:00 UTC 이후의 초 수입니다(그 이전의 타임스탬프에 대해서는 음수). for 및 값, 시간대 또는 일광 절약 시간에 관계없이 1970-01-01 00:00:00 이후의 공칭 초 수입니다. 값의 경우 간격의 총 시간(초)timestamp with time zonedatetimestampinterval
HOUR 시간 필드(0–23)
ISODOW 월요일(1)에서 일요일(7)
ISOYEAR 날짜가 속하는 ISO 8601 번호 매기기 연도(간격에는 적용되지 않음)
JULIAN 날짜 또는 타임스탬프에 해당하는 율리우스력 날짜입니다(간격에는 적용되지 않음). 로컬 자정이 아닌 타임스탬프는 소수 값이 됩니다
MICROSECONDS () 필드(소수 부분 포함) 1,000,000 곱합니다. 여기에는 전체 초가 포함됩니다
MILLENNIUM 복천년 - (1900년대는 번째 천년기입니다. 번째 천년기는 2001 1 1일에 시작되었습니다.)
MILLISECONDS () 필드(소수 부분 포함) 1000 곱합니다. 여기에는 전체 초가 포함됩니다.
MINUTE 필드(0–59)
MONTH 값의 경우 연도 내의 월 수(1–12) ; 값의 경우 개월 수,
QUARTER 날짜가 있는 연도의 분기(1–4)
SECOND () 필드(소수 자릿수 포함)
WEEK 해당 연도의 ISO 8601 주 번호 매기기 주의 번호입니다. 정의에 따라 ISO 주는 월요일에 시작하고 연도의 첫 번째 주에는 해당 연도의 1월 4일이 포함됩니다. 즉, 연도의 첫 번째 목요일은 해당 연도의 1주차에 있습니다.

ISO
주 번호 매기기 시스템에서는 1월 초 날짜가 전년도의 52번째 주 또는 53번째 주에 속하고 12월 말 날짜가 다음 해 첫 번째 주에 포함될 수 있습니다. 예를 들어 는 2004년 53번째 주의 일부이고, 는 2005년의 52번째 주의 일부이며, 는 2013년 첫째 주의 일부입니다. 일관된 결과를 얻으려면 필드를 함께 사용하는 것이 좋습니다.
YEAR 연도 필드입니다. 는 없으므로 몇 년에서 몇 년을 빼는 것은 주의해서 수행해야 합니다.

 

[ 관련예시 ]

select date_part('CENTURY'     , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 21

select date_part('DAY'         , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 25

select date_part('DECADE'      , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 202

select date_part('DOW'         , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 3

select date_part('DOY'         , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 25

select date_part('EPOCH'       , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 1674656360.01846

select date_part('HOUR'        , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 14

select date_part('ISODOW'      , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 3

select date_part('ISOYEAR'     , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 2023

select date_part('JULIAN'      , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 2459970.59675928

select date_part('MICROSECONDS', '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 20018460

select date_part('MILLENNIUM'  , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 3

select date_part('MILLISECONDS', '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 20018.46

select date_part('MINUTE'      , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 19

select date_part('MONTH'       , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 1

select date_part('QUARTER'     , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 1

select date_part('SECOND'      , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 20.01846

select date_part('WEEK'        , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 4

select date_part('YEAR'        , '2023-01-25 14:19:20.01846'::timestamp);
--출력결과(예시) : 2023
 

#참조 : PostgreSQL: Documentation: 15: 9.9. Date/Time Functions and Operators

이번에는 날짜/시간 형식에 알아보도록 하겠다.

형식 크기 설명 별칭
timestamp [(p)] [without time zone] 8 바이트 날짜와 시간 모두  
timestamp [(p)] [with time zone] 8 바이트 날짜와 시간 모두 시간대 포함 timestamptz
interval [(p)] 12 바이트 시간 간격  
date 4 바이트 날짜  
time [(p)] [without time zone] 8 바이트 시간  
time [(p)] with time zone 12 바이트 시간, 시간대 첨부 timetz

해당 타입으로 구성 할 수 있는 형태는 date, time, timestamp(date + ' ' + time) 세가지가 존재 하며, 아래와 같은 형태의 데이터 값을 사용 할 수 있다.

1. Dates

Example Description
1999-01-08 ISO 8601; January 8 in any mode (recommended format)
January 8, 1999 unambiguous in any input modedatestyle
1/8/1999 January 8 in mode; August 1 in modeMDYDMY
1/18/1999 January 18 in mode; rejected in other modesMDY
01/02/03 January 2, 2003 in mode; February 1, 2003 in mode; February 3, 2001 in modeMDYDMYYMD
1999-Jan-08 January 8 in any mode
Jan-08-1999 January 8 in any mode
08-Jan-1999 January 8 in any mode
99-Jan-08 January 8 in mode, else errorYMD
08-Jan-99 January 8, except error in modeYMD
Jan-08-99 January 8, except error in modeYMD
19990108 ISO 8601; January 8, 1999 in any mode
990108 ISO 8601; January 8, 1999 in any mode
1999.008 year and day of year
J2451187 Julian date
January 8, 99 BC year 99 BC

 

2-1. Times

Example Description
04:05:06.789 ISO 8601
04:05:06 ISO 8601
04:05 ISO 8601
040506 ISO 8601
04:05 AM same as 04:05; AM does not affect value
04:05 PM same as 16:05; input hour must be <= 12
04:05:06.789-8 ISO 8601, with time zone as UTC offset
04:05:06-08:00 ISO 8601, with time zone as UTC offset
04:05-08:00 ISO 8601, with time zone as UTC offset
040506-08 ISO 8601, with time zone as UTC offset
040506+0730 ISO 8601, with fractional-hour time zone as UTC offset
040506+07:30:00 UTC offset specified to seconds (not allowed in ISO 8601)
04:05:06 PST time zone specified by abbreviation
2003-04-12 04:05:06 America/New_York time zone specified by full name

2-2. Times Zone Input

Example Description
PST Abbreviation (for Pacific Standard Time)
America/New_York Full time zone name
PST8PDT POSIX-style time zone specification
-8:00:00 UTC offset for PST
-8:00 UTC offset for PST (ISO 8601 extended format)
-800 UTC offset for PST (ISO 8601 basic format)
-8 UTC offset for PST (ISO 8601 basic format)
zulu Military abbreviation for UTC
z Short form of (also in ISO 8601)zulu

#참조 : PostgreSQL: Documentation: 11: 8.5. Date/Time Types

 

※ 해당 내용은 날짜/시간 형식에 대해서만 기술해 보았다.

    이런 타입을 통해서 다양한 활용이 가능한데 이부분은 추후 알아 볼 예정입니다. ^^

이번에는 PostgreSQL의 문자열 타입을 알아보도록 하겠다.

우선 아래와같이 매우심플하다. 보통 nvarchar()를 지원하는데 Pg에는 지원하지 않는다.

* 참고

  - varchar : 영어,숫자=1Byte, 한글,한자등=2Byte

  - nvarchar : 모든문자열=2Byte

형식 크기 별칭
character varying(n) 가변 길이 문자열 varchar(n)
character(n) 고정 길이 문자열 char(n)
text 제한없이 가변 길이  

그렇다면 여기서 nvarchar가 존재 하지 않는다면, 문자열 길이 계산은 어떻게 될까를 알아보았다.

--char_length  : 문자열의 문자 수
--bit_length   : 문자열의 비트 수
--octet_length : 문자열의 바이트 수
SELECT m_char
     , char_length(m_char)
      , bit_length(m_char)
      , octet_length(m_char)
  FROM test3

Byte 기준으로 보았을때, Postgre SQL의 경우 한글의 경우 무려 3Byte를 차지하는걸 알수있었다. 

함수를 이용한 비트,바이트수 계산은 3Byte 이지만!, 실제로 컬럼 타입설정시 DataType에서 설정한 길이수 기준은

실제 데이터 insert등의 경우 숫자,영문,한글 모두 한글자(1)로 처리되어 동일하게 사용가능하다. 

이점에 유념해서 컬럼 DataType선언을 하기 바란다. ^^

 

Azure PostgreSQL 작업중 기타 서비스(DataFactory) 등에서 호출하여 사용할 목적으로 Truncate Table을 

하는 프로시저가 필요함에 따라 프로시저를 만들어 보았다. 실제로 Azure Pg라서 그런지는 모르겠지만 몇몇

방식은 에러가 발생하였고, 세부적인 여러 기능은 필요시마다 해당 블로그 글을 업데이트 할예정이며, 현재는 

필요한 프로시저 생성문만 정리 해본다.

 

아래 문장의 경우 TRUCATE TABLE 처리를 하며, 파라미터 값에 따라 유동적으로 스키마,테이블명이 바껴야한다.

이럴경우 DECLARE 로 변수를 선언하여, SQL쿼리문장을 담은 후 조합된 해당 문장을 EXCUTE하여야 한다.


CREATE PROCEDURE "ods"."sp_truncate_table" (schema_name varchar(15), tbl_name varchar(50))
LANGUAGE plpgsql
AS $$
DECLARE EXEC_SQL text;
BEGIN
    EXEC_SQL = 'TRUNCATE TABLE ' || schema_name || '.'|| tbl_name ;
    EXECUTE EXEC_SQL;
END;
$$  


/*CALL ods.sp_truncate_table ('[스키마명]','[테이블명]')*/
CALL ods.sp_truncate_table ('ods','test')
 
 

#참고 : PostgreSQL: Documentation: 15: CREATE PROCEDURE

 

 

PostgreSQL데이터 타입과  MS SQL 데이터 타입과의 비교.

Data type PostgreSQL SQL Server
64-bit integer BIGINT BIGINT
Fixed length byte string BYTEA BINARY(n)
1, 0 or NULL BOOLEAN BIT
Fixed length char string, 1 <= n <= 8000 CHAR(n) CHAR(n)
Variable length char string, 1 <= n <= 8000 VARCHAR(n) VARCHAR(n)
Variable length char string, <= 2GB TEXT VARCHAR(max)
Variable length byte string , 1 <= n <= 8000 BYTEA VARBINARY(n)
Variable length byte string , <= 2GB BYTEA VARBINARY(max)
Variable length Unicode UCS-2 string VARCHAR(n) NVARCHAR(n)
Variable length Unicode UCS-2 data, <= 2GB TEXT NVARCHAR(max)
Variable length character data, <= 2GB TEXT TEXT
Variable length Unicode UCS-2 data, <= 2GB TEXT NTEXT
Double precision floating point number DOUBLE PRECISION DOUBLE PRECISION
Floating point number DOUBLE PRECISION FLOAT(p)
32 bit integer INTEGER INTEGER
Fixed point number NUMERIC(p,s) NUMERIC(p,s)
Date includes year, month, and day DATE DATE
Date and time with fractional seconds TIMESTAMP(p) DATETIME, DATETIME2(p)
Date and time with time zone TIMESTAMP(p) WITH TIME ZONE DATETIMEOFFSET(p)
Date and time TIMESTAMP(0) SMALLDATETIME
Unsigned integer, 0 to 255 (8 bit) SMALLINT TINYINT
UUID (16 byte) CHAR(16) -> CHAR(36)    *16자리로는 Mig 불가능. UNIQUEIDENTIFIER
Automatically updated binary data BYTEA ROWVERSION
Currency amount (32 bit) MONEY SMALLMONEY
Variable length binary data, <= 2GB BYTEA IMAGE
Geometric types POINT, LINE, LSEG, BOX, PATH, POLYGON, CIRCLE GEOMETRY

#참조 : PostgreSQL vs. SQL Server (MSSQL) - Extremely Detailed Comparison (enterprisedb.com)

3-2와 같이 테이블 스키마 권한을 부여했지만 select시 없는 테이블로 나옴.

ERROR: relation "ods.test" does not exist LINE 2: from "ods".test ^ SQL state: 42P01 Character: 20
SQL state : 42P01

ERROR:  permission denied for schema mart
SQL state: 42501

아래와 같이 권한 부여에도 테이블 조회가 되지 않는다.
GRANT SELECT ON ALL TABLES IN SCHEMA ods TO adbuser;

 

/*권한부여된 테이블 조회하기*/
select table_schema, table_name
from information_schema.tables
where not table_schema='pg_catalog'
and not table_schema='information_schema';

해당문제를 팀원과 같이 알아보던중 해결책을 찾을 수 있었다.

------------------------------------------------------------------------------------------------
GRANT
USAGE ON SCHEMA <schema_name> TO <db_user>;
------------------------------------------------------------------------------------------------

해당 구문을 실행하여... 스키마를 사용 할 수 있는 권한을 부여해줘야 한다.
분명이 table select등 권한을 부여했음에도 또 저런 구문을 이용하여 줘야 되는지? 의문이 들었다.

이 부분은 기존에 GRANT SELELC ON~ 명령이 스키마안의 테이블에 대한 권한을 부여하는거라면 스키마 자체또한 객체로 보고, 해당 객체(스키마)에도 접속할 수 있는 액세스 권한을 부여하여야 하기에 GRANT USAGE ON SCHEMA 명령을 사용해야 되는걸로 확인되었다.

※ 여러 MS Azure Doc사이트 문서, 인터넷 검색등을 통해서도 저부분까지 표기되어 있는부분이 별로 없었다.
  실제 테스트를 기본적으로 제공되는 'public' 스키마를 써서 할텐데 이 경우 아마 디폴트로 'public'스키마는
  사용자(role)을 생성시 기본으로 객체 권한이 부여되는듯 하다. 그러므로 해당 명령수행을 놓치걸로 판단된다.

여러 시스템(사용자)이 DB에 접근 할 수 있으므로 권한을 통제를 할 필요가 있다.
이 경우 크게 두가지(관리자,사용자) 케이스가 있을 수 있다. 

1. Azure Database for PostgreSQL 추가관리자 만들기

CREATE ROLE <new_user> WITH LOGIN NOSUPERUSER INHERIT CREATEDB CREATEROLE NOREPLICATION PASSWORD '<StrongPassword!>';

GRANT azure_pg_admin TO <new_user>;


2. Azure Database for PostgreSQL 사용자 만들기

CREATE ROLE <db_user> WITH LOGIN NOSUPERUSER INHERIT CREATEDB NOCREATEROLE NOREPLICATION PASSWORD '<StrongPassword!>';

GRANT CONNECT ON DATABASE "<db_name>" TO <db_user>;
 
 
--스키마 테이블 SELECT권한부여
GRANT SELECT ON ALL TABLES IN SCHEMA <schema_name> TO <db_user>;
 
--[[추가]] 권한부여후 추가되는 테이블에 자동권한 부여하기. 
ALTER DEFAULT PRIVILEGES IN SCHEMA <schema_name>  GRANT SELECT ON TABLES TO <db_user>;
 
※ 추가적으로 UPDATE, INSERT, DELETE 권한 부여 필요시... 위에 쿼리 참고해서 적용.
 
 
▶ 추가로 자세한 데이터베이스 사용자의 역할 및 권한은 PostgreSQL설명서를 참고.
 
3. Azure Database for PostgreSQL Role 정보 확인
 
    SELECT * FROM PG_ROLES;
이름 설명
rolname name 역할 이름
rolsuper bool 슈퍼 유저 권한의 유무
rolinherit bool 멤버 롤의 권한을 상속할지 여부
rolcreaterole bool 역할 만들기 권한의 유무
rolcreatedb bool 데이터베이스 생성 권한이 있는지
rolcanlogin bool 로그인을 수있는 역할 여부
rolreplication bool 복제에 대한 역할 여부
rolconnlimit int4 최대 동시 연결 (-1 무제한)
rolpassword text 비밀번호 (다만, ******** 같이 표시)
rolvaliduntil timestamptz 암호 만료 (만료되지 않으면 NULL)
rolbypassrls bool 모든 단위 보안 정책을 무시할지 여부
rolconfig text[] 런타임 구성 변수에 대한 역할 기본
oid oid 롤의 ID

 

#참조 :  사용자 만들기 - Azure Database for PostgreSQL - 단일 서버 | Microsoft Learn

스키마 관련 명령어에 대해 알아본다. 사용방법은 간단하다.

--1-1.스키마 생성
CREATE SCHEMA SchmaName AUTHORIZATION UserName;

--1-2.스키마 삭제
DROP SCHEMA SchmaName CASCADE;

--1-3.스키마명 변경
ALTER SCHEMA SchmaName RENAME TO New_SchmaName;


--2.스키마 소유자 변경
ALTER SCHEMA UserName OWNER TO New_UserName;

 

PostgreSQL DB의 자동증가형식 Data Type을 알아보자. 통상적으로 사용되는 타입들의 자세한 설명은 Pass 하도록 하겠다.

 

: 자동증가형식(smallserial, serial, bigserial)

  * 해당 데이터 형식 지정시 별도로 데이터를 입력하지 않아도 자동으로 데이터가 증가한다.

    단, 수치값은 지금까지 사용된 값보다 큰값을 저장 할 뿐이지 현재 데이터의 max값 기준으로 설정되지는 않는다.

    MS-SQL에서 IDENTITY 타입과 동일,유사하다고 보면 된다.

형식 크기 범위 별칭
smallserial 2 바이트 1~32767 serial2
serial 4 바이트 1~2147483647 serial4
bigserial 8 바이트 1~9223372036854775807 serial8

  [체크포인트]

  보통 MS-SQL에서는 id열은 별도의 값을 지정해서 넣을수 없지만 PostgreSQL에서는 기본적으로 가능함.

  (MS-SQL등에서도 옵션지정을 통해가능. 방법은 추후 블로그에 기재)

  ★중요

    위에서 id = 4 값을 입력하며, 해당 자동증가값을 사용했다고 생각했고, 다시 id값을 별도로 지정하지 않았으니

    다음값을 자동채번->5 될지 알았지만 해당 채번은 사용되지 않음이 확인 되었다. (중복 발생)

  ※ 기존 사용됐던 id값을 삭제했을경우 재사용하는 용도로는 사용해도 되겠지만,

      이렇게 아직 미사용한 채번(자동증가) 값을 사용 할 경우 중복이 발생하니 이점에 유념하여 작업하기 바란다.

 

PostgreSQL DB의 숫자형식 Data Type을 알아보자. 통상적으로 사용되는 타입들의 자세한 설명은 Pass 하도록 하겠다.

 

: 정수형식(smallint, integer, bigint)

형식 크기 범위 별칭
smallint 2 바이트 -32768에서 +32767 int2
integer 4 바이트 -2147483648에서 +2147483647 int, int4
bigint 8 바이트 -9223372036854775808에서 +9223372036854775807 int8

 

: 정밀숫자형(numeric, decimal)

타입 크기 특징 범위 별칭
numeric 가변 사용자 지정, 정확 소수점 131072 자리까지 소수점 아래는 16,383 자리까지 decimal

   ▶ numeric(precision, scale)

      - precision(전체자리수) : scale(소수부) 포함 전체 숫자의 길이.

        * 지정된 길이보다 정수부(+소수점) 길이가 크면 Error.   

      - scale(소수부) : 소수부의 최대 길이.

        * 지정된 길이보다 소수점이 크면 반올림.       

   ▶ numeric(precision)

       - scale(소수부)를 지정하지 않고 사용가능하다. 단, 이 경우 소수점 존재데이터를 Insert할 경우 반올림처리된다.

         예) numeric(4) - 1000.9 insert

               = 결과 : 1001

       - 성능측면에서 굳이 소수점을 사용할께 아니라면 정수형식 type을 사용.

       

: 부동소수점(numeric, decimal)

형식 크기 특징 범위 별칭
real 4 바이트 가변 정밀도, 부정확 최소 6 자리의 정밀도 (적어도 1E-37에서 1E + 37) float4
double precision 8 바이트 가변 정밀도, 부정확 최소 15 자리의 정밀도 ( 1E-307에서 1E + 308) float8

 * 정해진 타입의 길이내에서 소수점이 사용가능하며, 자리수 초과시 반올림 처리된다.

 

+ Recent posts