blob: 70f896170e7f1bcdaaa881876d99467c87706bc7 [file] [log] [blame]
David Friedmanc921ee12015-06-29 22:14:16 -07001page.title=SQL 데이터베이스에 데이터 저장하기
2page.tags=data storage
3helpoutsWidget=true
4
5trainingnavtop=true
6
7@jd:body
8
9
10<div id="tb-wrapper">
11<div id="tb">
12
13<h2> 과정에서 다루는 내용</h2>
14<ol>
15 <li><a href="#DefineContract">스키마 계약 정의하기</a></li>
16 <li><a href="#DbHelper">SQL Helper 사용하여 데이터베이스 생성하기</a></li>
17 <li><a href="#WriteDbRow">데이터베이스에 정보 삽입하기</a></li>
18 <li><a href="#ReadDbRow">데이터베이스에서 정보 읽어오기</a></li>
19 <li><a href="#DeleteDbRow">데이터베이스에서 정보 삭제하기</a></li>
20 <li><a href="#UpdateDbRow">데이터베이스 업데이트하기</a></li>
21</ol>
22
23<h2>필독 항목</h2>
24<ul>
25 <li><a href="{@docRoot}guide/topics/data/data-storage.html#db">데이터베이스 사용하기</a></li>
26</ul>
27
28<!--
29<h2>Try it out</h2>
30
31<div class="download-box">
32 <a href="{@docRoot}shareables/training/Sample.zip" class="button">Download the sample</a>
33 <p class="filename">Sample.zip</p>
34</div>
35-->
36
37</div>
38</div>
39
40
41<p>데이터베이스에 데이터를 저장하는 작업은
42연락처 정보와 같이 반복적이거나 구조적인 데이터에 이상적입니다. 클래스에서는 사용자가 SQL 데이터베이스에 대한 기본 사항에
43익숙하다는 전제하에
44Android에서 SQLite 데이터베이스를 시작하는 도움이 되는 유용한 정보를 제공합니다. Android에서
45데이터베이스를 사용할 필요한 API {@link android.database.sqlite} 패키지에 있습니다.</p>
46
47
48<h2 id="DefineContract">스키마 계약 정의하기</h2>
49
50<p>SQL 데이터베이스의 기본 원칙 하나는 스키마입니다. 스키마는 데이터베이스의 구성 체계에 대한 공식적인
51선언입니다. 스키마는 개발자가 데이터베이스를 생성할 사용하는 SQL
52문에 반영됩니다. <em>계약</em> 클래스라고 하는
53도우미 클래스를 생성하면 도움이 있습니다. 계약 클래스는 체계적이고
54자기 문서화 방식으로 스키마의 레이아웃을 명시적으로 지정합니다.</p>
55
56<p>계약 클래스는 URI, 테이블
57컬럼의 이름을 정의하는 상수를 유지하는 컨테이너입니다. 계약 클래스를 사용하면 동일한 패키지
58모든 클래스에 동일한 상수를 사용할 있습니다. 즉, 어느 장소에서 컬럼
59이름을 변경하면 코드 전체에 변경 사항이 반영됩니다.</p>
60
61<p>계약 클래스를 구성하는 좋은 방법은 클래스의 루트 레벨에 전체 데이터베이스에
62전역적인 정의를 추가하는 것입니다. 그런 다음 컬럼을 열거하는 테이블에 대해 내부
63클래스를 생성합니다.</p>
64
65<p class="note"><strong>참고:</strong> {@link
66android.provider.BaseColumns} 인터페이스를 구현함으로써, 내부 클래스는 {@code _ID}라고 하는 기본
67 필드를 상속할 있습니다. 커서 어댑터와 같은 일부 Android 클래스의 경우
68내부 클래스가 이러한 기본 필드를 가지고 있을 것이라 예상합니다. 내부 클래스는 반드시 필요한 것은 아니지만, 데이터베이스가
69Android 프레임워크와 조화롭게 작업하는 도움이 있습니다.</p>
70
71<p>예를 들어, 다음 스니펫은 테이블 이름과
72단일 테이블의 컬럼 이름을 정의합니다.</p>
73
74
75<pre>
76public final class FeedReaderContract {
77 // To prevent someone from accidentally instantiating the contract class,
78 // give it an empty constructor.
79 public FeedReaderContract() {}
80
81 /* Inner class that defines the table contents */
82 public static abstract class FeedEntry implements BaseColumns {
83 public static final String TABLE_NAME = &quot;entry&quot;;
84 public static final String COLUMN_NAME_ENTRY_ID = &quot;entryid&quot;;
85 public static final String COLUMN_NAME_TITLE = &quot;title&quot;;
86 public static final String COLUMN_NAME_SUBTITLE = &quot;subtitle&quot;;
87 ...
88 }
89}
90</pre>
91
92
93
94<h2 id="DbHelper">SQL Helper 사용하여 데이터베이스 생성하기</h2>
95
96<p>데이터베이스의 모양을 정의한 후에는 데이터베이스 테이블을 생성 유지하는
97메서드를 구현해야 합니다. 다음은 테이블을 생성하고 삭제하는 가지 일반적인
98명령문입니다.</P>
99
100<pre>
101private static final String TEXT_TYPE = &quot; TEXT&quot;;
102private static final String COMMA_SEP = &quot;,&quot;;
103private static final String SQL_CREATE_ENTRIES =
104 &quot;CREATE TABLE &quot; + FeedEntry.TABLE_NAME + &quot; (&quot; +
105 FeedEntry._ID + &quot; INTEGER PRIMARY KEY,&quot; +
106 FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP +
107 FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP +
108 ... // Any other options for the CREATE command
109 &quot; )&quot;;
110
111private static final String SQL_DELETE_ENTRIES =
112 &quot;DROP TABLE IF EXISTS &quot; + FeedEntry.TABLE_NAME;
113</pre>
114
115<p>기기의 <a href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">내부
116저장소</a>에 저장하는 파일과 같이, Android 데이터베이스를
117애플리케이션과 관련된 개인 디스크 공간에 저장합니다. 기본적으로 공간은 다른 애플리케이션이
118액세스할 없기 때문에 저장된 데이터는 안전하게 유지됩니다.</p>
119
120<p>유용한 API 집합이 {@link
Mark Luc4a01392016-07-18 10:42:11 -0700121android.database.sqlite.SQLiteOpenHelper} 클래스에서 제공됩니다.
David Friedmanc921ee12015-06-29 22:14:16 -0700122데이터베이스에 대한 참조를 가져오기 위해 클래스를 사용하는 경우, 시스템은
Mark Luc4a01392016-07-18 10:42:11 -0700123필요한 경우에 한해서만 데이터베이스 생성 업데이트와 같이
David Friedmanc921ee12015-06-29 22:14:16 -0700124장시간 실행될 있는 작업을
Mark Luc4a01392016-07-18 10:42:11 -0700125수행하며, <em>앱이 시작되는 동안에는 이러한 작업을 수행하지 않습니다</em>.
126{@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 또는
David Friedmanc921ee12015-06-29 22:14:16 -0700127{@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase}를 호출하기만 하면 됩니다.</p>
128
Mark Luc4a01392016-07-18 10:42:11 -0700129<p class="note"><strong>참고:</strong> 이러한 작업은 장시간 실행될 수도 있기 때문에
David Friedmanc921ee12015-06-29 22:14:16 -0700130{@link android.os.AsyncTask} 또는 {@link android.app.IntentService}와 같이 백그라운드 스레드에서 {@link
131android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 또는 {@link
132android.database.sqlite.SQLiteOpenHelper#getReadableDatabase}를
133호출해야 합니다.</p>
134
135<p>{@link android.database.sqlite.SQLiteOpenHelper}를 사용하려면 {@link
136android.database.sqlite.SQLiteOpenHelper#onCreate onCreate()}, {@link
137android.database.sqlite.SQLiteOpenHelper#onUpgrade onUpgrade()} 및 {@link
138android.database.sqlite.SQLiteOpenHelper#onOpen onOpen()} 콜백 메서드를
139재정의하는 하위 클래스를 생성합니다. 반드시 필요한 것은 아니지만
140{@link android.database.sqlite.SQLiteOpenHelper#onDowngrade onDowngrade()}도 구현해야 하는
141경우가 있을 있습니다.</p>
142
143<p>다음은 위에 표시된 명령 일부를 사용하여 구현한 {@link
144android.database.sqlite.SQLiteOpenHelper}의 예입니다.</p>
145
146<pre>
147public class FeedReaderDbHelper extends SQLiteOpenHelper {
148 // If you change the database schema, you must increment the database version.
149 public static final int DATABASE_VERSION = 1;
150 public static final String DATABASE_NAME = &quot;FeedReader.db&quot;;
151
152 public FeedReaderDbHelper(Context context) {
153 super(context, DATABASE_NAME, null, DATABASE_VERSION);
154 }
155 public void onCreate(SQLiteDatabase db) {
156 db.execSQL(SQL_CREATE_ENTRIES);
157 }
158 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
159 // This database is only a cache for online data, so its upgrade policy is
160 // to simply to discard the data and start over
161 db.execSQL(SQL_DELETE_ENTRIES);
162 onCreate(db);
163 }
164 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
165 onUpgrade(db, oldVersion, newVersion);
166 }
167}
168</pre>
169
170<p>데이터베이스에 액세스하려면 {@link
171android.database.sqlite.SQLiteOpenHelper}의 하위 클래스를 인스턴스화합니다.</p>
172
173<pre>
174FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext());
175</pre>
176
177
178
179
180<h2 id="WriteDbRow">데이터베이스에 정보 삽입하기</h2>
181
182<p>{@link android.content.ContentValues}
183개체를 {@link android.database.sqlite.SQLiteDatabase#insert insert()} 메서드에 전달하여 데이터를 데이터베이스에 삽입합니다.</p>
184
185<pre>
186// Gets the data repository in write mode
187SQLiteDatabase db = mDbHelper.getWritableDatabase();
188
189// Create a new map of values, where column names are the keys
190ContentValues values = new ContentValues();
191values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);
192values.put(FeedEntry.COLUMN_NAME_TITLE, title);
193values.put(FeedEntry.COLUMN_NAME_CONTENT, content);
194
195// Insert the new row, returning the primary key value of the new row
196long newRowId;
197newRowId = db.insert(
198 FeedEntry.TABLE_NAME,
199 FeedEntry.COLUMN_NAME_NULLABLE,
200 values);
201</pre>
202
203<p>{@link android.database.sqlite.SQLiteDatabase#insert insert()}의
204 번째 인수는 테이블 이름입니다. 번째 인수는
205컬럼 이름을 제공합니다. 프레임워크는 {@link android.content.ContentValues}가 비어있을 경우
206여기에 NULL 삽입할 있습니다. 만약 이를 {@code "null"}로 설정할 경우,
207값이 없으면 프레임워크가 행을 삽입하지 않습니다.</p>
208
209
210
211
212<h2 id="ReadDbRow">데이터베이스에서 정보 읽어오기</h2>
213
214<p>데이터베이스로부터 정보를 읽어오려면 {@link android.database.sqlite.SQLiteDatabase#query query()}
215메서드를 사용하고, 선택 기준과 원하는 컬럼을 전달합니다.
216 메서드는 {@link android.database.sqlite.SQLiteDatabase#insert insert()}
217 {@link android.database.sqlite.SQLiteDatabase#update update()} 요소를 결합합니다. 단, 삽입하려는 데이터보다는 가져오려는 데이터를
218정의하는 컬럼 목록은 예외입니다. 쿼리 결과는
219{@link android.database.Cursor} 개체로 반환됩니다.</p>
220
221<pre>
222SQLiteDatabase db = mDbHelper.getReadableDatabase();
223
224// Define a <em>projection</em> that specifies which columns from the database
225// you will actually use after this query.
226String[] projection = {
227 FeedEntry._ID,
228 FeedEntry.COLUMN_NAME_TITLE,
229 FeedEntry.COLUMN_NAME_UPDATED,
230 ...
231 };
232
233// How you want the results sorted in the resulting Cursor
234String sortOrder =
235 FeedEntry.COLUMN_NAME_UPDATED + " DESC";
236
237Cursor c = db.query(
238 FeedEntry.TABLE_NAME, // The table to query
239 projection, // The columns to return
240 selection, // The columns for the WHERE clause
241 selectionArgs, // The values for the WHERE clause
242 null, // don't group the rows
243 null, // don't filter by row groups
244 sortOrder // The sort order
245 );
246</pre>
247
248<p>커서 안의 행을 보려면 {@link android.database.Cursor} 이동
249메서드 하나를 사용합니다. 메서드는 값을 읽어오기 전에 항상 먼저 호출해야 합니다. 일반적으로 결과의
250처음 항목에 "읽기 위치" 배치하는 {@link android.database.Cursor#moveToFirst}를 먼저
251호출해야 합니다. {@link android.database.Cursor#getString
252getString()} 또는 {@link android.database.Cursor#getLong getLong()}과 같은 {@link android.database.Cursor} 가져오기 메서드
253 하나를 호출하여 행에 대한 컬럼 값을 읽어올 있습니다. 가져오기 메서드 각각에 대해
254원하는 컬럼의 인덱스 위치를 전달해야 하며, 이는
255{@link android.database.Cursor#getColumnIndex getColumnIndex()} 또는
256{@link android.database.Cursor#getColumnIndexOrThrow getColumnIndexOrThrow()}를 호출하여 가져올 수 있습니다.
257예를 들면 다음과 같습니다.</p>
258
259<pre>
260cursor.moveToFirst();
261long itemId = cursor.getLong(
262 cursor.getColumnIndexOrThrow(FeedEntry._ID)
263);
264</pre>
265
266
267
268
269<h2 id="DeleteDbRow">데이터베이스에서 정보 삭제하기</h2>
270
271<p>테이블에서 행을 삭제하려면 행을
272식별하는 선택 기준을 제공해야 합니다. 데이터베이스 API SQL 삽입을 방지하는 선택
273기준을 생성하는 메커니즘을 제공합니다. 메커니즘은
274선택 사양을 선택 절과 선택 인수로 나눕니다. 절은
275보려는 컬럼을 정의하고, 이를 통해 컬럼
276테스트를 결합할 있습니다. 인수는 안에 묶여 테스트되는 값입니다.
277 결과는 일반 SQL 문과 같이 처리되지 않기 때문에 SQL 삽입의
278영향을 받지 않습니다.</p>
279
280<pre>
281// Define 'where' part of query.
282String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + &quot; LIKE ?&quot;;
283// Specify arguments in placeholder order.
284String[] selectionArgs = { String.valueOf(rowId) };
285// Issue SQL statement.
286db.delete(table_name, selection, selectionArgs);
287</pre>
288
289
290
291<h2 id="UpdateDbRow">데이터베이스 업데이트하기</h2>
292
293<p>데이터베이스 값의 하위 세트를 수정해야 하는 경우, {@link
294android.database.sqlite.SQLiteDatabase#update update()} 메서드를 사용합니다.</p>
295
296<p>테이블을 업데이트하면 {@link
297android.database.sqlite.SQLiteDatabase#insert insert()}의 콘텐츠 값 구문과
298{@link android.database.sqlite.SQLiteDatabase#delete delete()}의 {@code where} 구문이 결합됩니다.</p>
299
300<pre>
301SQLiteDatabase db = mDbHelper.getReadableDatabase();
302
303// New value for one column
304ContentValues values = new ContentValues();
305values.put(FeedEntry.COLUMN_NAME_TITLE, title);
306
307// Which row to update, based on the ID
308String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + &quot; LIKE ?&quot;;
309String[] selectionArgs = { String.valueOf(rowId) };
310
311int count = db.update(
312 FeedReaderDbHelper.FeedEntry.TABLE_NAME,
313 values,
314 selection,
315 selectionArgs);
316</pre>
317