메뉴 건너뛰기

Korea Oracle User Group

23c Free Developer Release

JSON-Relational Duality View 튜토리얼

명품관 2023.04.10 16:39 조회 수 : 60

JSON-Relational Duality View 튜토리얼

 

오라클 23c Free Developer Release로 이번에 홍보하는 내용 중에 하나인 

JSON-Relational Duality View를 오라클이 제공한 튜토리얼 문서의 내용으로 테스트 해 보았다.

 

기능적인면과 활용성 면에서 어떤 기대를 할 수 있을지 알아볼 수 있는 시간으면 합니다.

 

1. 튜토리얼 내용을 수행하기 위해 초기 세팅

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
SQL> SET ECHO ON
SQL> SET FEEDBACK 1
SQL> SET NUMWIDTH 10
SQL> SET LINESIZE 80
SQL> SET TRIMSPOOL ON
SQL> SET TAB OFF
SQL> SET PAGESIZE 100
SQL> SET LONG 20000
SQL> drop view  if exists team_dv;
 
뷰가 삭제되었습니다.
 
SQL> drop view  if exists race_dv;
 
뷰가 삭제되었습니다.
 
SQL> drop view  if exists driver_dv;
 
뷰가 삭제되었습니다.
 
SQL> drop table if exists driver_race_map;
 
테이블이 삭제되었습니다.
 
SQL> drop table if exists race;
 
테이블이 삭제되었습니다.
 
SQL> drop table if exists driver;
 
테이블이 삭제되었습니다.
 
SQL> drop table if exists team;
 
테이블이 삭제되었습니다.

 

2. 테스트에 사용할 테이블 4개 생성

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
SQL> CREATE TABLE team
  2    (team_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
  3     name    VARCHAR2(255NOT NULL UNIQUE,
  4     points  INTEGER NOT NULL,
  5     CONSTRAINT team_pk PRIMARY KEY(team_id));
 
테이블이 생성되었습니다.
 
SQL> CREATE TABLE driver
  2    (driver_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
  3     name      VARCHAR2(255NOT NULL UNIQUE,
  4     points    INTEGER NOT NULL,
  5     team_id   INTEGER,
  6     CONSTRAINT driver_pk PRIMARY KEY(driver_id),
  7     CONSTRAINT driver_fk FOREIGN KEY(team_id) REFERENCES team(team_id));
 
테이블이 생성되었습니다.
 
SQL> CREATE TABLE race
  2    (race_id   INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
  3     name      VARCHAR2(255NOT NULL UNIQUE,
  4     laps      INTEGER NOT NULL,
  5     race_date DATE,
  6     podium    JSON,
  7     CONSTRAINT   race_pk PRIMARY KEY(race_id));
 
테이블이 생성되었습니다.
 
SQL> CREATE TABLE driver_race_map
  2    (driver_race_map_id INTEGER GENERATED BY DEFAULT ON NULL AS IDENTITY,
  3     race_id            INTEGER NOT NULL,
  4     driver_id          INTEGER NOT NULL,
  5     position           INTEGER,
  6     CONSTRAINT     driver_race_map_uk  UNIQUE (race_id, driver_id),
  7     CONSTRAINT     driver_race_map_pk  PRIMARY KEY(driver_race_map_id),
  8     CONSTRAINT     driver_race_map_fk1 FOREIGN KEY(race_id)   REFERENCES race(race_id),
  9     CONSTRAINT     driver_race_map_fk2 FOREIGN KEY(driver_id) REFERENCES driver(driver_id));
 
테이블이 생성되었습니다.

 

 

3. driver_race_map 테이블에 트리거 생성

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
SQL> CREATE OR REPLACE TRIGGER driver_race_map_trigger
  2    BEFORE INSERT ON driver_race_map
  3    FOR EACH ROW
  4    DECLARE
  5      v_points  INTEGER;
  6      v_team_id INTEGER;
  7  BEGIN
  8    SELECT team_id INTO v_team_id FROM driver WHERE driver_id = :NEW.driver_id;
  9  
 10    IF :NEW.position = 1 THEN
 11      v_points := 25;
 12    ELSIF :NEW.position = 2 THEN
 13      v_points := 18;
 14    ELSIF :NEW.position = 3 THEN
 15      v_points := 15;
 16    ELSIF :NEW.position = 4 THEN
 17      v_points := 12;
 18    ELSIF :NEW.position = 5 THEN
 19      v_points := 10;
 20    ELSIF :NEW.position = 6 THEN
 21      v_points := 8;
 22    ELSIF :NEW.position = 7 THEN
 23      v_points := 6;
 24    ELSIF :NEW.position = 8 THEN
 25      v_points := 4;
 26    ELSIF :NEW.position = 9 THEN
 27      v_points := 2;
 28    ELSIF :NEW.position = 10 THEN
 29      v_points := 1;
 30    ELSE
 31      v_points := 0;
 32    END IF;
 33  
 34    UPDATE driver SET points = points + v_points
 35      WHERE driver_id = :NEW.driver_id;
 36    UPDATE team SET points = points + v_points
 37      WHERE team_id = v_team_id;
 38  END;
 39  /
 
트리거가 생성되었습니다.

 

4. JSON-Relational Duality View를 생성하고 초기 데이터 없음을 확인

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
SQL> CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW race_dv AS
  2    SELECT JSON {'raceId' : r.race_id,
  3                 'name'   : r.name,
  4                 'laps'   : r.laps WITH NOUPDATE,
  5                 'date'   : r.race_date,
  6                 'podium' : r.podium WITH NOCHECK,
  7                 'result' :
  8                   [ SELECT JSON {'driverRaceMapId' : drm.driver_race_map_id,
  9                                  'position'        : drm.position,
 10                                  UNNEST
 11                                    (SELECT JSON {'driverId' : d.driver_id,
 12                                                  'name'     : d.name}
 13                                       FROM driver d WITH NOINSERT UPDATE NODELETE
 14                                       WHERE d.driver_id = drm.driver_id)}
 15                       FROM driver_race_map drm WITH INSERT UPDATE DELETE
 16                       WHERE drm.race_id = r.race_id ]}
 17      FROM race r WITH INSERT UPDATE DELETE;
 
뷰가 생성되었습니다.
 
SQL> CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW driver_dv AS
  2    SELECT JSON {'driverId' : d.driver_id,
  3                 'name'     : d.name,
  4                 'points'   : d.points,
  5                 UNNEST
  6                   (SELECT JSON {'teamId' : t.team_id,
  7                                 'team'   : t.name WITH NOCHECK}
  8                      FROM team t WITH NOINSERT NOUPDATE NODELETE
  9                      WHERE t.team_id = d.team_id),
 10                 'race'     :
 11                   [ SELECT JSON {'driverRaceMapId' : drm.driver_race_map_id,
 12                                  UNNEST
 13                                    (SELECT JSON {'raceId' : r.race_id,
 14                                                  'name'   : r.name}
 15                                       FROM race r WITH NOINSERT NOUPDATE NODELETE
 16                                       WHERE r.race_id = drm.race_id),
 17                                  'finalPosition'   : drm.position}
 18                      FROM driver_race_map drm WITH INSERT UPDATE NODELETE
 19                      WHERE drm.driver_id = d.driver_id ]}
 20      FROM driver d WITH INSERT UPDATE DELETE;
  
뷰가 생성되었습니다.
 
SQL> CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW team_dv AS
  2    SELECT JSON {'teamId' : t.team_id,
  3                 'name'   : t.name,
  4                 'points' : t.points,
  5                 'driver' :
  6                   [ SELECT JSON {'driverId' : d.driver_id,
  7                                  'name'     : d.name,
  8                                  'points'   : d.points WITH NOCHECK}
  9                       FROM driver d WITH INSERT UPDATE
 10                       WHERE d.team_id = t.team_id ]}
 11      FROM team t WITH INSERT UPDATE DELETE;
 
뷰가 생성되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM driver_dv;
 
선택된 레코드가 없습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM race_dv;
 
선택된 레코드가 없습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM team_dv;
 
선택된 레코드가 없습니다.

 

JSON-Relation Duality View를 생성하는 구문을 확인할 수 있다.

CREATE OR REPLACE JSON RELATIONAL DUALITY VIEW 구문으로 생성한다.

일반 뷰와 같이 Select 문장이 뒤따르면서 조회되는 내용을 쿼리 하는 것을 볼 수 있다.

특이한 부분은 뷰의 마지막 부분에 WITH INSERT UPDATE DELETE 구문이 있어 DML이 가능한 것을 알 수 있다.

 

JSON 구문에 내부 element 정의에 또 SQL 문장을 사용하는 식으로 문장을 만들게 된다.

뷰 생성 후 json_serialize 함수를 사용해 데이터를 조회해 본다.

데이터 생성을 하지 않았기 때문에 데이터는 현재 조회되지 않는다.

 

5. 뷰를 사용한 INSERT 문 수행

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
SQL> INSERT INTO team_dv VALUES ('{"teamId" : 301,
  2                                "name"   : "Red Bull",
  3                                "points" : 0,
  4                                "driver" : [ {"driverId" : 101,
  5                                              "name"     : "Max Verstappen",
  6                                              "points"   : 0},
  7                                             {"driverId" : 102,
  8                                              "name"     : "Sergio Perez",
  9                                              "points"   : 0} ]}');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO team_dv VALUES ('{"teamId" : 302,
  2                                "name"   : "Ferrari",
  3                                "points" : 0,
  4                                "driver" : [ {"driverId" : 103,
  5                                              "name"     : "Charles Leclerc",
  6                                              "points"   : 0},
  7                                             {"driverId" : 104,
  8                                              "name"     : "Carlos Sainz Jr",
  9                                              "points"   : 0} ]}');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO team_dv VALUES ('{"teamId" : 2,
  2                                "name"   : "Mercedes",
  3                                "points" : 0,
  4                                "driver" : [ {"driverId" : 105,
  5                                              "name"     : "George Russell",
  6                                              "points"   : 0},
  7                                             {"driverId" : 106,
  8                                              "name"     : "Lewis Hamilton",
  9                                              "points"   : 0} ]}');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO race_dv VALUES ('{"raceId" : 201,
  2                                "name"   : "Bahrain Grand Prix",
  3                                "laps"   : 57,
  4                                "date"   : "2022-03-20T00:00:00",
  5                                "podium" : {}}');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO race_dv VALUES ('{"raceId" : 202,
  2                                "name"   : "Saudi Arabian Grand Prix",
  3                                "laps"   : 50,
  4                                "date"   : "2022-03-27T00:00:00",
  5                                "podium" : {}}');
 
1 개의 행이 만들어졌습니다.
 
SQL> INSERT INTO race_dv VALUES ('{"raceId" : 203,
  2                                "name"   : "Australian Grand Prix",
  3                                "laps"   : 58,
  4                                "date"   : "2022-04-09T00:00:00",
  5                                "podium" : {}}');
 
1 개의 행이 만들어졌습니다.
 
SQL> COMMIT;
 
커밋이 완료되었습니다.

 

뷰를 통해 insert 하고 있으며 values 절에 JSON 구문으로 데이터를 구성한다.

team_dv와 race_dv를 통해 데이터를 insert 했다.

하지만 team_dv에 입력할 때 driver 부분도 같이 데이터를 입력했다. 

 

6. View를 각각 조회해 봄

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
SQL> SELECT json_serialize(data PRETTY) FROM driver_dv;
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "F9D9815DFF27879F61386CFD1622B065",
    "asof" : "00000000002EE42A"
  },
  "driverId" : 101,
  "name" : "Max Verstappen",
  "points" : 0,
  "teamId" : 301,
  "team" : "Red Bull",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "9865A29DEE5F5754674A9B1D2EC58730",
    "asof" : "00000000002EE42A"
  },
  "driverId" : 102,
  "name" : "Sergio Perez",
  "points" : 0,
  "teamId" : 301,
  "team" : "Red Bull",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "C47A91F57BF3CF45F0D8284240399A90",
    "asof" : "00000000002EE42A"
  },
  "driverId" : 103,
  "name" : "Charles Leclerc",
  "points" : 0,
  "teamId" : 302,
  "team" : "Ferrari",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "363EC6BBF0FADD913B219482959DA39D",
    "asof" : "00000000002EE42A"
  },
  "driverId" : 104,
  "name" : "Carlos Sainz Jr",
  "points" : 0,
  "teamId" : 302,
  "team" : "Ferrari",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "A8BB1825F6218EC0D300671173540597",
    "asof" : "00000000002EE42A"
  },
  "driverId" : 105,
  "name" : "George Russell",
  "points" : 0,
  "teamId" : 2,
  "team" : "Mercedes",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "D3FF3213793E306204BB5E5060368E41",
    "asof" : "00000000002EE42A"
  },
  "driverId" : 106,
  "name" : "Lewis Hamilton",
  "points" : 0,
  "teamId" : 2,
  "team" : "Mercedes",
  "race" :
  [
  ]
}
 
 
6 행이 선택되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM race_dv;
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "2E8DC09543DD25DC7D588FB9734D962B",
    "asof" : "00000000002EE42C"
  },
  "raceId" : 201,
  "name" : "Bahrain Grand Prix",
  "laps" : 57,
  "date" : "2022-03-20T00:00:00",
  "podium" :
  {
  },
  "result" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "7E056A845212BFDE19E0C0D0CD549EA0",
    "asof" : "00000000002EE42C"
  },
  "raceId" : 202,
  "name" : "Saudi Arabian Grand Prix",
  "laps" : 50,
  "date" : "2022-03-27T00:00:00",
  "podium" :
  {
  },
  "result" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "EA6E1194C012970CA07116EE1EF167E8",
    "asof" : "00000000002EE42C"
  },
  "raceId" : 203,
  "name" : "Australian Grand Prix",
  "laps" : 58,
  "date" : "2022-04-09T00:00:00",
  "podium" :
  {
  },
  "result" :
  [
  ]
}
 
3 행이 선택되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM team_dv;
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "9F0F855A39F4AE8FECD7E6A123855FD1",
    "asof" : "00000000002EEEB8"
  },
  "teamId" : 301,
  "name" : "Red Bull",
  "points" : 0,
  "driver" :
  [
    {
      "driverId" : 101,
      "name" : "Max Verstappen",
      "points" : 0
    },
    {
      "driverId" : 102,
      "name" : "Sergio Perez",
      "points" : 0
    }
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "DD9401D853765859714A6B8176BFC564",
    "asof" : "00000000002EEEB8"
  },
  "teamId" : 302,
  "name" : "Ferrari",
  "points" : 30,
  "driver" :
  [
    {
      "driverId" : 104,
      "name" : "Carlos Sainz Jr",
      "points" : 18
    },
    {
      "driverId" : 105,
      "name" : "George Russell",
      "points" : 12
    }
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "9E266CD7554A89663B73B9977B1F967C",
    "asof" : "00000000002EEEB8"
  },
  "teamId" : 2,
  "name" : "Mercedes",
  "points" : 40,
  "driver" :
  [
    {
      "driverId" : 103,
      "name" : "Charles Leclerc",
      "points" : 25
    },
    {
      "driverId" : 106,
      "name" : "Lewis Hamilton",
      "points" : 15
    }
  ]
}
 
 
3 행이 선택되었습니다.

 

7. 조건절 사용, 정렬, 특정 구성요소 조회 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
SQL> SELECT json_serialize(data PRETTY)
  2    FROM race_dv WHERE json_value(data, '$.raceId'= 201;
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "2E8DC09543DD25DC7D588FB9734D962B",
    "asof" : "00000000002EE432"
  },
  "raceId" : 201,
  "name" : "Bahrain Grand Prix",
  "laps" : 57,
  "date" : "2022-03-20T00:00:00",
  "podium" :
  {
  },
  "result" :
  [
  ]
}
 
 
1개의 행이 선택되었습니다.
 
SQL> SELECT json_serialize(json_transform(data, KEEP '$.name''$.team') PRETTY)
  2    FROM driver_dv;
 
JSON_SERIALIZE(JSON_TRANSFORM(DATA,KEEP'$.NAME','$.TEAM')PRETTY)
--------------------------------------------------------------------------------
{
  "name" : "Max Verstappen",
  "team" : "Red Bull"
}
 
{
  "name" : "Sergio Perez",
  "team" : "Red Bull"
}
 
{
  "name" : "Charles Leclerc",
  "team" : "Ferrari"
}
 
{
  "name" : "Carlos Sainz Jr",
  "team" : "Ferrari"
}
 
{
  "name" : "George Russell",
  "team" : "Mercedes"
}
 
{
  "name" : "Lewis Hamilton",
  "team" : "Mercedes"
}
 
 
6 행이 선택되었습니다.
 
SQL> SELECT json_serialize(json_transform(data, KEEP '$.name''$.team') PRETTY)
  2    FROM driver_dv ORDER BY json_value(data, '$.team');
 
JSON_SERIALIZE(JSON_TRANSFORM(DATA,KEEP'$.NAME','$.TEAM')PRETTY)
--------------------------------------------------------------------------------
{
  "name" : "Charles Leclerc",
  "team" : "Ferrari"
}
 
{
  "name" : "Carlos Sainz Jr",
  "team" : "Ferrari"
}
 
{
  "name" : "George Russell",
  "team" : "Mercedes"
}
 
{
  "name" : "Lewis Hamilton",
  "team" : "Mercedes"
}
 
{
  "name" : "Max Verstappen",
  "team" : "Red Bull"
}
 
{
  "name" : "Sergio Perez",
  "team" : "Red Bull"
}
 
 
6 행이 선택되었습니다.

 

조회를 위해 구문에 대해서 알아둘 필요가 있을 거 같다.

일반 SQL 문장과 다른 점들이 있으니 활용을 위해서는 기본적인 부분에 대해서 알아둬야 할 거 같다.

 

8. UPDATE 문을 통해 전체 document data 변경

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
SQL> UPDATE race_dv dv
  2    SET data = ('{_metadata : {"etag" : "2E8DC09543DD25DC7D588FB9734D962B"},
  3                  "raceId" : 201,
  4                  "name"   : "Bahrain Grand Prix",
  5                  "laps"   : 57,
  6                  "date"   : "2022-03-20T00:00:00",
  7                  "podium" :
  8                    {"winner"         : {"name" : "Charles Leclerc",
  9                                         "time" : "01:37:33.584"},
 10                     "firstRunnerUp"  : {"name" : "Carlos Sainz Jr",
 11                                         "time" : "01:37:39.182"},
 12                     "secondRunnerUp" : {"name" : "Lewis Hamilton",
 13                                         "time" : "01:37:43.259"}},
 14                  "result" : [ {"driverRaceMapId" : 3,
 15                                "position"        : 1,
 16                                "driverId"        : 103,
 17                                "name"            : "Charles Leclerc"},
 18                               {"driverRaceMapId" : 4,
 19                                "position"        : 2,
 20                                "driverId"        : 104,
 21                                "name"            : "Carlos Sainz Jr"},
 22                               {"driverRaceMapId" : 9,
 23                                "position"        : 3,
 24                                "driverId"        : 106,
 25                                "name"            : "Lewis Hamilton"},
 26                               {"driverRaceMapId" : 10,
 27                                "position"        : 4,
 28                                "driverId"        : 105,
 29                                "name"            : "George Russell"} ]}')
 30      WHERE dv.data.raceId = 201;
 
1 행이 업데이트되었습니다.
 
SQL> COMMIT;
 
커밋이 완료되었습니다.
 
SQL> SELECT json_serialize(data PRETTY)
  2    FROM race_dv dv WHERE dv.data.raceId = 201;
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "20F7D9F0C69AC5F959DCA819F9116848",
    "asof" : "00000000002EE455"
  },
  "raceId" : 201,
  "name" : "Bahrain Grand Prix",
  "laps" : 57,
  "date" : "2022-03-20T00:00:00",
  "podium" :
  {
    "winner" :
    {
      "name" : "Charles Leclerc",
      "time" : "01:37:33.584"
    },
    "firstRunnerUp" :
    {
      "name" : "Carlos Sainz Jr",
      "time" : "01:37:39.182"
    },
    "secondRunnerUp" :
    {
      "name" : "Lewis Hamilton",
      "time" : "01:37:43.259"
    }
  },
  "result" :
  [
    {
      "driverRaceMapId" : 3,
      "position" : 1,
      "driverId" : 103,
      "name" : "Charles Leclerc"
    },
    {
      "driverRaceMapId" : 4,
      "position" : 2,
      "driverId" : 104,
      "name" : "Carlos Sainz Jr"
    },
    {
      "driverRaceMapId" : 9,
      "position" : 3,
      "driverId" : 106,
      "name" : "Lewis Hamilton"
    },
    {
      "driverRaceMapId" : 10,
      "position" : 4,
      "driverId" : 105,
      "name" : "George Russell"
    }
  ]
}
 
 
1개의 행이 선택되었습니다.

 

raceid 가 201인 document의 전체 내용을 update 하고 내용을 조회해 봤다.

 

9. 특정 조건의 특정 요소만 UPDATE

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
SQL> UPDATE race_dv dv
  2    SET data = json_transform(data, SET '$.name' = 'Blue Air Bahrain Grand Prix')
  3      WHERE dv.data.name LIKE 'Bahrain%';
 
1 행이 업데이트되었습니다.
 
SQL> COMMIT;
 
커밋이 완료되었습니다.
 
SQL> SELECT json_serialize(data PRETTY)
  2    FROM race_dv WHERE json_value(data, '$.name'LIKE 'Blue Air Bahrain%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "F6906A8F7A131C127FAEF32CA43AF97A",
    "asof" : "00000000002EE460"
  },
  "raceId" : 201,
  "name" : "Blue Air Bahrain Grand Prix",
  "laps" : 57,
  "date" : "2022-03-20T00:00:00",
  "podium" :
  {
    "winner" :
    {
      "name" : "Charles Leclerc",
      "time" : "01:37:33.584"
    },
    "firstRunnerUp" :
    {
      "name" : "Carlos Sainz Jr",
      "time" : "01:37:39.182"
    },
    "secondRunnerUp" :
    {
      "name" : "Lewis Hamilton",
      "time" : "01:37:43.259"
    }
  },
  "result" :
  [
    {
      "driverRaceMapId" : 3,
      "position" : 1,
      "driverId" : 103,
      "name" : "Charles Leclerc"
    },
    {
      "driverRaceMapId" : 4,
      "position" : 2,
      "driverId" : 104,
      "name" : "Carlos Sainz Jr"
    },
    {
      "driverRaceMapId" : 9,
      "position" : 3,
      "driverId" : 106,
      "name" : "Lewis Hamilton"
    },
    {
      "driverRaceMapId" : 10,
      "position" : 4,
      "driverId" : 105,
      "name" : "George Russell"
    }
  ]
}
 
 
1개의 행이 선택되었습니다.
 
SQL> UPDATE race_dv dv
  2    SET data = json_mergepatch(data, '{"name" : "Blue Air Bahrain Grand Prix"}')
  3      WHERE dv.data.name LIKE 'Blue Air Bahrain%';
 
1 행이 업데이트되었습니다.
 
SQL> COMMIT;
 
커밋이 완료되었습니다.
 
SQL> SELECT json_serialize(data PRETTY)
  2    FROM race_dv WHERE json_value(data, '$.name'LIKE 'Blue Air Bahrain%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "F6906A8F7A131C127FAEF32CA43AF97A",
    "asof" : "00000000002EE46A"
  },
  "raceId" : 201,
  "name" : "Blue Air Bahrain Grand Prix",
  "laps" : 57,
  "date" : "2022-03-20T00:00:00",
  "podium" :
  {
    "winner" :
    {
      "name" : "Charles Leclerc",
      "time" : "01:37:33.584"
    },
    "firstRunnerUp" :
    {
      "name" : "Carlos Sainz Jr",
      "time" : "01:37:39.182"
    },
    "secondRunnerUp" :
    {
      "name" : "Lewis Hamilton",
      "time" : "01:37:43.259"
    }
  },
  "result" :
  [
    {
      "driverRaceMapId" : 3,
      "position" : 1,
      "driverId" : 103,
      "name" : "Charles Leclerc"
    },
    {
      "driverRaceMapId" : 4,
      "position" : 2,
      "driverId" : 104,
      "name" : "Carlos Sainz Jr"
    },
    {
      "driverRaceMapId" : 9,
      "position" : 3,
      "driverId" : 106,
      "name" : "Lewis Hamilton"
    },
    {
      "driverRaceMapId" : 10,
      "position" : 4,
      "driverId" : 105,
      "name" : "George Russell"
    }
  ]
}
 
 
1개의 행이 선택되었습니다.

 

10. 드라이버의 팀 이동을 위해 team_dv 뷰에서 update

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
SQL> SELECT json_serialize(data PRETTY) FROM team_dv dv
  2    WHERE dv.data.name LIKE 'Mercedes%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "855840B905C8CAFA99FB9CBF813992E5",
    "asof" : "00000000002EE46F"
  },
  "teamId" : 2,
  "name" : "Mercedes",
  "points" : 27,
  "driver" :
  [
    {
      "driverId" : 105,
      "name" : "George Russell",
      "points" : 12
    },
    {
      "driverId" : 106,
      "name" : "Lewis Hamilton",
      "points" : 15
    }
  ]
}
 
 
1개의 행이 선택되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM team_dv dv
  2    WHERE dv.data.name LIKE 'Ferrari%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "C5DD30F04DA1A6A390BFAB12B7D4F700",
    "asof" : "00000000002EE46F"
  },
  "teamId" : 302,
  "name" : "Ferrari",
  "points" : 43,
  "driver" :
  [
    {
      "driverId" : 103,
      "name" : "Charles Leclerc",
      "points" : 25
    },
    {
      "driverId" : 104,
      "name" : "Carlos Sainz Jr",
      "points" : 18
    }
  ]
}
 
 
1개의 행이 선택되었습니다.
 
SQL> UPDATE team_dv dv
  2    SET data = ('{_metadata : {"etag" : "855840B905C8CAFA99FB9CBF813992E5"},
  3                  "teamId" : 2,
  4                  "name"   : "Mercedes",
  5                  "points" : 40,
  6                  "driver" : [ {"driverId" : 106,
  7                                "name"     : "Lewis Hamilton",
  8                                "points"   : 15},
  9                               {"driverId" : 103,
 10                                "name"     : "Charles Leclerc",
 11                                "points"   : 25} ]}')
 12      WHERE dv.data.name LIKE 'Mercedes%';
 
1 행이 업데이트되었습니다.
 
SQL> UPDATE team_dv dv
  2    SET data = ('{_metadata : {"etag" : "DA69DD103E8BAE95A0C09811B7EC9628"},
  3                  "teamId" : 302,
  4                  "name"   : "Ferrari",
  5                  "points" : 30,
  6                  "driver" : [ {"driverId" : 105,
  7                                "name"     : "George Russell",
  8                                "points"   : 12},
  9                               {"driverId" : 104,
 10                                "name"     : "Carlos Sainz Jr",
 11                                "points"   : 18} ]}')
 12      WHERE dv.data.name LIKE 'Ferrari%';
 
1 행이 업데이트되었습니다.
 
SQL> COMMIT;
 
커밋이 완료되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM team_dv dv
  2    WHERE dv.data.name LIKE 'Mercedes%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "9E266CD7554A89663B73B9977B1F967C",
    "asof" : "00000000002EE4A1"
  },
  "teamId" : 2,
  "name" : "Mercedes",
  "points" : 40,
  "driver" :
  [
    {
      "driverId" : 103,
      "name" : "Charles Leclerc",
      "points" : 25
    },
    {
      "driverId" : 106,
      "name" : "Lewis Hamilton",
      "points" : 15
    }
  ]
}
 
 
1개의 행이 선택되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM team_dv dv
  2    WHERE dv.data.name LIKE 'Ferrari%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "DD9401D853765859714A6B8176BFC564",
    "asof" : "00000000002EE4A2"
  },
  "teamId" : 302,
  "name" : "Ferrari",
  "points" : 30,
  "driver" :
  [
    {
      "driverId" : 104,
      "name" : "Carlos Sainz Jr",
      "points" : 18
    },
    {
      "driverId" : 105,
      "name" : "George Russell",
      "points" : 12
    }
  ]
}
 
 
1개의 행이 선택되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM driver_dv dv
  2    WHERE dv.data.name LIKE 'Charles Leclerc%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "FCD4CEC63897F60DEA1EC2F64D3CE53A",
    "asof" : "00000000002EE4A6"
  },
  "driverId" : 103,
  "name" : "Charles Leclerc",
  "points" : 25,
  "teamId" : 2,
  "team" : "Mercedes",
  "race" :
  [
    {
      "driverRaceMapId" : 3,
      "raceId" : 201,
      "name" : "Blue Air Bahrain Grand Prix",
      "finalPosition" : 1
    }
  ]
}
 
 
1개의 행이 선택되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM driver_dv dv
  2    WHERE dv.data.name LIKE 'George Russell%';
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "1425B4FA21B8DFFF88BBC476E10F377D",
    "asof" : "00000000002EE4A7"
  },
  "driverId" : 105,
  "name" : "George Russell",
  "points" : 12,
  "teamId" : 302,
  "team" : "Ferrari",
  "race" :
  [
    {
      "driverRaceMapId" : 10,
      "raceId" : 201,
      "name" : "Blue Air Bahrain Grand Prix",
      "finalPosition" : 4
    }
  ]
}
 
 
1개의 행이 선택되었습니다.

 

11. 업데이트 불가능한 필드를 업데이트 할 경우

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
SQL> UPDATE driver_dv dv
  2    SET DATA = ('{_metadata : {"etag" : "FCD4CEC63897F60DEA1EC2F64D3CE53A"},
  3                  "driverId" : 103,
  4                  "name" : "Charles Leclerc",
  5                  "points" : 25,
  6                  "teamId" : 2,
  7                  "team" : "Ferrari",
  8                  "race" :
  9                  [
 10                    {
 11                      "driverRaceMapId" : 3,
 12                      "raceId" : 201,
 13                      "name" : "Blue Air Bahrain Grand Prix",
 14                      "finalPosition" : 1
 15                    }
 16                  ]
 17              }')
 18    WHERE dv.data.driverId = 103;
UPDATE driver_dv dv
*
1행에 오류:
ORA-40940: team 열(테이블: NAME, 뷰: TEAM)을 업데이트할 수 없습니다.

 

driver_dv 뷰를 업데이트시 team에 대해서는 업데이트를 할 수 없다

위와 같이 에러가 발생한다.

 

12. 조건에 맞는 데이터 DELETE

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
SQL> DELETE FROM race_dv dv WHERE dv.data.raceId = 201;
 
1 행이 삭제되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM race_dv;
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "7E056A845212BFDE19E0C0D0CD549EA0",
    "asof" : "00000000002EE4D0"
  },
  "raceId" : 202,
  "name" : "Saudi Arabian Grand Prix",
  "laps" : 50,
  "date" : "2022-03-27T00:00:00",
  "podium" :
  {
  },
  "result" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "EA6E1194C012970CA07116EE1EF167E8",
    "asof" : "00000000002EE4D0"
  },
  "raceId" : 203,
  "name" : "Australian Grand Prix",
  "laps" : 58,
  "date" : "2022-04-09T00:00:00",
  "podium" :
  {
  },
  "result" :
  [
  ]
}
 
 
2 행이 선택되었습니다.
 
SQL> SELECT json_serialize(data PRETTY) FROM driver_dv;
 
JSON_SERIALIZE(DATAPRETTY)
--------------------------------------------------------------------------------
{
  "_metadata" :
  {
    "etag" : "F9D9815DFF27879F61386CFD1622B065",
    "asof" : "00000000002EE4D1"
  },
  "driverId" : 101,
  "name" : "Max Verstappen",
  "points" : 0,
  "teamId" : 301,
  "team" : "Red Bull",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "9865A29DEE5F5754674A9B1D2EC58730",
    "asof" : "00000000002EE4D1"
  },
  "driverId" : 102,
  "name" : "Sergio Perez",
  "points" : 0,
  "teamId" : 301,
  "team" : "Red Bull",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "5B73D3125469F38033DA10BDF5FC693D",
    "asof" : "00000000002EE4D1"
  },
  "driverId" : 103,
  "name" : "Charles Leclerc",
  "points" : 25,
  "teamId" : 2,
  "team" : "Mercedes",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "8C9770E842C31AAD6AF45FB978F18238",
    "asof" : "00000000002EE4D1"
  },
  "driverId" : 104,
  "name" : "Carlos Sainz Jr",
  "points" : 18,
  "teamId" : 302,
  "team" : "Ferrari",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "C98F2BC901F43FFB046A137321573C12",
    "asof" : "00000000002EE4D1"
  },
  "driverId" : 105,
  "name" : "George Russell",
  "points" : 12,
  "teamId" : 302,
  "team" : "Ferrari",
  "race" :
  [
  ]
}
 
{
  "_metadata" :
  {
    "etag" : "D59ACFB934EE946D9E4B1FC9737E54F9",
    "asof" : "00000000002EE4D1"
  },
  "driverId" : 106,
  "name" : "Lewis Hamilton",
  "points" : 15,
  "teamId" : 2,
  "team" : "Mercedes",
  "race" :
  [
  ]
}
 
 
6 행이 선택되었습니다.
 
SQL> COMMIT;
 
커밋이 완료되었습니다.

 

13. 마무리

 

document 구조의 JSON 데이터를 위와 같이 사용할 수 있다고 오라클이 제공하는 튜토리얼의 스크립트를 테스트해 봤다.

RDB의 데이터 구조와 같이 사용이 가능한지 혹은 더 밀접하게 같이 사용 가능한지 여부는 

더 많은 테스트를 해 봐야 알 것같다.

 

이번 테스트는 이 정도에서 마무리하도록 하겠다. 

위로