| page.title=SQL 데이터베이스에 데이터 저장하기 |
| page.tags=data storage |
| helpoutsWidget=true |
| |
| trainingnavtop=true |
| |
| @jd:body |
| |
| |
| <div id="tb-wrapper"> |
| <div id="tb"> |
| |
| <h2>이 과정에서 다루는 내용</h2> |
| <ol> |
| <li><a href="#DefineContract">스키마 및 계약 정의하기</a></li> |
| <li><a href="#DbHelper">SQL Helper를 사용하여 데이터베이스 생성하기</a></li> |
| <li><a href="#WriteDbRow">데이터베이스에 정보 삽입하기</a></li> |
| <li><a href="#ReadDbRow">데이터베이스에서 정보 읽어오기</a></li> |
| <li><a href="#DeleteDbRow">데이터베이스에서 정보 삭제하기</a></li> |
| <li><a href="#UpdateDbRow">데이터베이스 업데이트하기</a></li> |
| </ol> |
| |
| <h2>필독 항목</h2> |
| <ul> |
| <li><a href="{@docRoot}guide/topics/data/data-storage.html#db">데이터베이스 사용하기</a></li> |
| </ul> |
| |
| <!-- |
| <h2>Try it out</h2> |
| |
| <div class="download-box"> |
| <a href="{@docRoot}shareables/training/Sample.zip" class="button">Download the sample</a> |
| <p class="filename">Sample.zip</p> |
| </div> |
| --> |
| |
| </div> |
| </div> |
| |
| |
| <p>데이터베이스에 데이터를 저장하는 작업은 |
| 연락처 정보와 같이 반복적이거나 구조적인 데이터에 이상적입니다. 이 클래스에서는 사용자가 SQL 데이터베이스에 대한 기본 사항에 |
| 익숙하다는 전제하에 |
| Android에서 SQLite 데이터베이스를 시작하는 데 도움이 되는 유용한 정보를 제공합니다. Android에서 |
| 데이터베이스를 사용할 때 필요한 API는 {@link android.database.sqlite} 패키지에 있습니다.</p> |
| |
| |
| <h2 id="DefineContract">스키마 및 계약 정의하기</h2> |
| |
| <p>SQL 데이터베이스의 기본 원칙 중 하나는 스키마입니다. 스키마는 데이터베이스의 구성 체계에 대한 공식적인 |
| 선언입니다. 스키마는 개발자가 데이터베이스를 생성할 때 사용하는 SQL |
| 문에 반영됩니다. <em>계약</em> 클래스라고 하는 |
| 도우미 클래스를 생성하면 도움이 될 수 있습니다. 계약 클래스는 체계적이고 |
| 자기 문서화 방식으로 스키마의 레이아웃을 명시적으로 지정합니다.</p> |
| |
| <p>계약 클래스는 URI, 테이블 및 |
| 컬럼의 이름을 정의하는 상수를 유지하는 컨테이너입니다. 계약 클래스를 사용하면 동일한 패키지 내 |
| 모든 클래스에 동일한 상수를 사용할 수 있습니다. 즉, 어느 한 장소에서 컬럼 |
| 이름을 변경하면 코드 전체에 변경 사항이 반영됩니다.</p> |
| |
| <p>계약 클래스를 구성하는 좋은 방법은 클래스의 루트 레벨에 전체 데이터베이스에 |
| 전역적인 정의를 추가하는 것입니다. 그런 다음 컬럼을 열거하는 각 테이블에 대해 내부 |
| 클래스를 생성합니다.</p> |
| |
| <p class="note"><strong>참고:</strong> {@link |
| android.provider.BaseColumns} 인터페이스를 구현함으로써, 내부 클래스는 {@code _ID}라고 하는 기본 |
| 키 필드를 상속할 수 있습니다. 커서 어댑터와 같은 일부 Android 클래스의 경우 |
| 내부 클래스가 이러한 기본 키 필드를 가지고 있을 것이라 예상합니다. 내부 클래스는 반드시 필요한 것은 아니지만, 데이터베이스가 |
| Android 프레임워크와 조화롭게 작업하는 데 도움이 될 수 있습니다.</p> |
| |
| <p>예를 들어, 다음 스니펫은 테이블 이름과 |
| 단일 테이블의 컬럼 이름을 정의합니다.</p> |
| |
| |
| <pre> |
| public final class FeedReaderContract { |
| // To prevent someone from accidentally instantiating the contract class, |
| // give it an empty constructor. |
| public FeedReaderContract() {} |
| |
| /* Inner class that defines the table contents */ |
| public static abstract class FeedEntry implements BaseColumns { |
| public static final String TABLE_NAME = "entry"; |
| public static final String COLUMN_NAME_ENTRY_ID = "entryid"; |
| public static final String COLUMN_NAME_TITLE = "title"; |
| public static final String COLUMN_NAME_SUBTITLE = "subtitle"; |
| ... |
| } |
| } |
| </pre> |
| |
| |
| |
| <h2 id="DbHelper">SQL Helper를 사용하여 데이터베이스 생성하기</h2> |
| |
| <p>데이터베이스의 모양을 정의한 후에는 데이터베이스 및 테이블을 생성 및 유지하는 |
| 메서드를 구현해야 합니다. 다음은 테이블을 생성하고 삭제하는 몇 가지 일반적인 |
| 명령문입니다.</P> |
| |
| <pre> |
| private static final String TEXT_TYPE = " TEXT"; |
| private static final String COMMA_SEP = ","; |
| private static final String SQL_CREATE_ENTRIES = |
| "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" + |
| FeedEntry._ID + " INTEGER PRIMARY KEY," + |
| FeedEntry.COLUMN_NAME_ENTRY_ID + TEXT_TYPE + COMMA_SEP + |
| FeedEntry.COLUMN_NAME_TITLE + TEXT_TYPE + COMMA_SEP + |
| ... // Any other options for the CREATE command |
| " )"; |
| |
| private static final String SQL_DELETE_ENTRIES = |
| "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME; |
| </pre> |
| |
| <p>기기의 <a href="{@docRoot}guide/topics/data/data-storage.html#filesInternal">내부 |
| 저장소</a>에 저장하는 파일과 같이, Android는 데이터베이스를 |
| 애플리케이션과 관련된 개인 디스크 공간에 저장합니다. 기본적으로 이 공간은 다른 애플리케이션이 |
| 액세스할 수 없기 때문에 저장된 데이터는 안전하게 유지됩니다.</p> |
| |
| <p>유용한 API 집합이 {@link |
| android.database.sqlite.SQLiteOpenHelper} 클래스에서 제공됩니다. |
| 데이터베이스에 대한 참조를 가져오기 위해 이 클래스를 사용하는 경우, 시스템은 |
| 필요한 경우에 한해서만 데이터베이스 생성 및 업데이트와 같이 |
| 장시간 실행될 수 있는 작업을 |
| 수행하며, <em>앱이 시작되는 동안에는 이러한 작업을 수행하지 않습니다</em>. |
| {@link android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 또는 |
| {@link android.database.sqlite.SQLiteOpenHelper#getReadableDatabase}를 호출하기만 하면 됩니다.</p> |
| |
| <p class="note"><strong>참고:</strong> 이러한 작업은 장시간 실행될 수도 있기 때문에 |
| {@link android.os.AsyncTask} 또는 {@link android.app.IntentService}와 같이 백그라운드 스레드에서 {@link |
| android.database.sqlite.SQLiteOpenHelper#getWritableDatabase} 또는 {@link |
| android.database.sqlite.SQLiteOpenHelper#getReadableDatabase}를 |
| 호출해야 합니다.</p> |
| |
| <p>{@link android.database.sqlite.SQLiteOpenHelper}를 사용하려면 {@link |
| android.database.sqlite.SQLiteOpenHelper#onCreate onCreate()}, {@link |
| android.database.sqlite.SQLiteOpenHelper#onUpgrade onUpgrade()} 및 {@link |
| android.database.sqlite.SQLiteOpenHelper#onOpen onOpen()} 콜백 메서드를 |
| 재정의하는 하위 클래스를 생성합니다. 반드시 필요한 것은 아니지만 |
| {@link android.database.sqlite.SQLiteOpenHelper#onDowngrade onDowngrade()}도 구현해야 하는 |
| 경우가 있을 수 있습니다.</p> |
| |
| <p>다음은 위에 표시된 명령 중 일부를 사용하여 구현한 {@link |
| android.database.sqlite.SQLiteOpenHelper}의 예입니다.</p> |
| |
| <pre> |
| public class FeedReaderDbHelper extends SQLiteOpenHelper { |
| // If you change the database schema, you must increment the database version. |
| public static final int DATABASE_VERSION = 1; |
| public static final String DATABASE_NAME = "FeedReader.db"; |
| |
| public FeedReaderDbHelper(Context context) { |
| super(context, DATABASE_NAME, null, DATABASE_VERSION); |
| } |
| public void onCreate(SQLiteDatabase db) { |
| db.execSQL(SQL_CREATE_ENTRIES); |
| } |
| public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
| // This database is only a cache for online data, so its upgrade policy is |
| // to simply to discard the data and start over |
| db.execSQL(SQL_DELETE_ENTRIES); |
| onCreate(db); |
| } |
| public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { |
| onUpgrade(db, oldVersion, newVersion); |
| } |
| } |
| </pre> |
| |
| <p>데이터베이스에 액세스하려면 {@link |
| android.database.sqlite.SQLiteOpenHelper}의 하위 클래스를 인스턴스화합니다.</p> |
| |
| <pre> |
| FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext()); |
| </pre> |
| |
| |
| |
| |
| <h2 id="WriteDbRow">데이터베이스에 정보 삽입하기</h2> |
| |
| <p>{@link android.content.ContentValues} |
| 개체를 {@link android.database.sqlite.SQLiteDatabase#insert insert()} 메서드에 전달하여 데이터를 데이터베이스에 삽입합니다.</p> |
| |
| <pre> |
| // Gets the data repository in write mode |
| SQLiteDatabase db = mDbHelper.getWritableDatabase(); |
| |
| // Create a new map of values, where column names are the keys |
| ContentValues values = new ContentValues(); |
| values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id); |
| values.put(FeedEntry.COLUMN_NAME_TITLE, title); |
| values.put(FeedEntry.COLUMN_NAME_CONTENT, content); |
| |
| // Insert the new row, returning the primary key value of the new row |
| long newRowId; |
| newRowId = db.insert( |
| FeedEntry.TABLE_NAME, |
| FeedEntry.COLUMN_NAME_NULLABLE, |
| values); |
| </pre> |
| |
| <p>{@link android.database.sqlite.SQLiteDatabase#insert insert()}의 |
| 첫 번째 인수는 테이블 이름입니다. 두 번째 인수는 |
| 컬럼 이름을 제공합니다. 프레임워크는 {@link android.content.ContentValues}가 비어있을 경우 |
| 여기에 NULL을 삽입할 수 있습니다. 만약 이를 {@code "null"}로 설정할 경우, |
| 값이 없으면 프레임워크가 행을 삽입하지 않습니다.</p> |
| |
| |
| |
| |
| <h2 id="ReadDbRow">데이터베이스에서 정보 읽어오기</h2> |
| |
| <p>데이터베이스로부터 정보를 읽어오려면 {@link android.database.sqlite.SQLiteDatabase#query query()} |
| 메서드를 사용하고, 선택 기준과 원하는 컬럼을 전달합니다. |
| 이 메서드는 {@link android.database.sqlite.SQLiteDatabase#insert insert()} |
| 및 {@link android.database.sqlite.SQLiteDatabase#update update()} 요소를 결합합니다. 단, 삽입하려는 데이터보다는 가져오려는 데이터를 |
| 정의하는 컬럼 목록은 예외입니다. 쿼리 결과는 |
| {@link android.database.Cursor} 개체로 반환됩니다.</p> |
| |
| <pre> |
| SQLiteDatabase db = mDbHelper.getReadableDatabase(); |
| |
| // Define a <em>projection</em> that specifies which columns from the database |
| // you will actually use after this query. |
| String[] projection = { |
| FeedEntry._ID, |
| FeedEntry.COLUMN_NAME_TITLE, |
| FeedEntry.COLUMN_NAME_UPDATED, |
| ... |
| }; |
| |
| // How you want the results sorted in the resulting Cursor |
| String sortOrder = |
| FeedEntry.COLUMN_NAME_UPDATED + " DESC"; |
| |
| Cursor c = db.query( |
| FeedEntry.TABLE_NAME, // The table to query |
| projection, // The columns to return |
| selection, // The columns for the WHERE clause |
| selectionArgs, // The values for the WHERE clause |
| null, // don't group the rows |
| null, // don't filter by row groups |
| sortOrder // The sort order |
| ); |
| </pre> |
| |
| <p>커서 안의 행을 보려면 {@link android.database.Cursor} 이동 |
| 메서드 중 하나를 사용합니다. 이 메서드는 값을 읽어오기 전에 항상 먼저 호출해야 합니다. 일반적으로 결과의 |
| 처음 항목에 "읽기 위치"를 배치하는 {@link android.database.Cursor#moveToFirst}를 먼저 |
| 호출해야 합니다. {@link android.database.Cursor#getString |
| getString()} 또는 {@link android.database.Cursor#getLong getLong()}과 같은 {@link android.database.Cursor} 가져오기 메서드 |
| 중 하나를 호출하여 각 행에 대한 컬럼 값을 읽어올 수 있습니다. 가져오기 메서드 각각에 대해 |
| 원하는 컬럼의 인덱스 위치를 전달해야 하며, 이는 |
| {@link android.database.Cursor#getColumnIndex getColumnIndex()} 또는 |
| {@link android.database.Cursor#getColumnIndexOrThrow getColumnIndexOrThrow()}를 호출하여 가져올 수 있습니다. |
| 예를 들면 다음과 같습니다.</p> |
| |
| <pre> |
| cursor.moveToFirst(); |
| long itemId = cursor.getLong( |
| cursor.getColumnIndexOrThrow(FeedEntry._ID) |
| ); |
| </pre> |
| |
| |
| |
| |
| <h2 id="DeleteDbRow">데이터베이스에서 정보 삭제하기</h2> |
| |
| <p>테이블에서 행을 삭제하려면 행을 |
| 식별하는 선택 기준을 제공해야 합니다. 데이터베이스 API는 SQL 삽입을 방지하는 선택 |
| 기준을 생성하는 메커니즘을 제공합니다. 이 메커니즘은 |
| 선택 사양을 선택 절과 선택 인수로 나눕니다. 절은 |
| 보려는 컬럼을 정의하고, 이를 통해 컬럼 |
| 테스트를 결합할 수 있습니다. 인수는 절 안에 묶여 테스트되는 값입니다. |
| 이 결과는 일반 SQL 문과 같이 처리되지 않기 때문에 SQL 삽입의 |
| 영향을 받지 않습니다.</p> |
| |
| <pre> |
| // Define 'where' part of query. |
| String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"; |
| // Specify arguments in placeholder order. |
| String[] selectionArgs = { String.valueOf(rowId) }; |
| // Issue SQL statement. |
| db.delete(table_name, selection, selectionArgs); |
| </pre> |
| |
| |
| |
| <h2 id="UpdateDbRow">데이터베이스 업데이트하기</h2> |
| |
| <p>데이터베이스 값의 하위 세트를 수정해야 하는 경우, {@link |
| android.database.sqlite.SQLiteDatabase#update update()} 메서드를 사용합니다.</p> |
| |
| <p>테이블을 업데이트하면 {@link |
| android.database.sqlite.SQLiteDatabase#insert insert()}의 콘텐츠 값 구문과 |
| {@link android.database.sqlite.SQLiteDatabase#delete delete()}의 {@code where} 구문이 결합됩니다.</p> |
| |
| <pre> |
| SQLiteDatabase db = mDbHelper.getReadableDatabase(); |
| |
| // New value for one column |
| ContentValues values = new ContentValues(); |
| values.put(FeedEntry.COLUMN_NAME_TITLE, title); |
| |
| // Which row to update, based on the ID |
| String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"; |
| String[] selectionArgs = { String.valueOf(rowId) }; |
| |
| int count = db.update( |
| FeedReaderDbHelper.FeedEntry.TABLE_NAME, |
| values, |
| selection, |
| selectionArgs); |
| </pre> |
| |