Outsider's Dev Story: Database/Commons 카테고리 글 목록https://blog.outsider.ne.kr/Stay Hungry. Stay Foolish. Don't Be Satisfied.2024-03-15T10:26:27+09:00Textcube 1.10.7 : Tempo primoAlembic으로 환경별 다른 데이터베이스 사용하기Outsiderhttps://blog.outsider.ne.kr/11462015-05-23T18:06:15+09:002015-05-23T18:06:15+09:00<p>데이터베이스의 스키마를 관리할 때 <a href="https://bitbucket.org/zzzeek/alembic">Alembic</a>을 <a href="http://blog.outsider.ne.kr/1143">사용하고 있다</a>.</p>
<pre class="line-numbers"><code class="language-clike">[alembic]
script_location = alembic
sqlalchemy.url = postgresql://user:password@host/db_name
</code></pre>
<p>Alembic에서는 데이터베이스 접속 정보를 <code>alembic.ini</code>에서 다음과 관리하고 있는데 <code>[alembic]</code>이라고 된 영역이 기본 설정이고 여기서 <code>sqlalchemy.url</code>에 데이터베이스 접속 정보를 보관하고 있다. 하지만 개발을 하면 로컬 데이터베이스도 있고 테스트나 스테이지 용 데이터베이스도 있고 실제 서비스를 하는 데이터베이스가 있는데 각 데이터베이스에서 스키마를 관리해 주어야 하므로 상황별로 다른 데이터베이스 접속 정보를 사용해야 한다.</p>
<blockquote>
<p>sqlalchemy.url - A URL to connect to the database via SQLAlchemy. This key is in fact only referenced within the env.py file that is specific to the “generic” configuration; a file that can be customized by the developer. A multiple database configuration may respond to multiple keys here, or may reference other sections of the file.</p>
</blockquote>
<p><a href="http://alembic.readthedocs.org/en/latest/tutorial.html">문서</a>에 따르면 <code>sqlalchemy.url</code>는 SQLAlchemy가 사용하는 데이터베이스 접속 URL이고 <code>env.py</code>파일에서만 사용하고 있다는 것이다. 이 값이나 <code>env.py</code>파일에서 이 값을 커스터마이징할 수 있는 것 같은데 SQLAlchemy를 안 쓰다 보니 정확한 방법을 알기가 어려웠고 대부분은 Python과 함께 쓰고 있으므로 애플리케이션에서 사용하는 데이터베이스 정보를 읽어와서 Alembic에서 사용하는 것으로 보였다. 나는 Alembic만 별도로 쓰고 있었으므로 이 방법을 적용하기가 어려웠고 SQLAlchemy도 전혀 몰라서 적용하기가 어려웠다.</p>
<p>여러 가지 시도 끝에 다음과 같이 영역을 여러 가지 만들어서 필요에 따라 다른 설정을 사용하도록 할 수 있다는 걸 알게 되었다.</p>
<pre class="line-numbers"><code class="language-clike">[alembic]
script_location = alembic
sqlalchemy.url = postgresql://user:password@host/db_name
[db_test]
script_location = alembic
sqlalchemy.url = postgresql://user:password@test_host/test_db_name
[db_stage]
script_location = alembic
sqlalchemy.url = postgresql://user:password@stage_host/stage_db_name
[db_production]
script_location = alembic
sqlalchemy.url = postgresql://user:password@production_host/production_db_name
</code></pre>
<p>스키마를 적용할 때 <code>alembic upgrade head</code>을 실행하면 <code>[alembic]</code>영역의 설정을 사용하지만 <code>alembic --name db_test upgrade head</code>처럼 <code>--name</code> 옵션으로 영역의 이름을 주면 해당 영역의 값을 사용하므로 서버 환경에 따라 다른 데이터베이스 정보를 사용할 수 있다. 서버의 환경변수별로 하고 싶기도 한데 아직은 그 방법을 잘 모르겠다.</p>
<p><strong><a href="https://blog.outsider.ne.kr/1146?commentInput=true#entry1146WriteComment">댓글 쓰기</a></strong></p>데이터베이스 마이그레이션 도구 alembicOutsiderhttps://blog.outsider.ne.kr/11432015-05-11T01:17:18+09:002015-05-11T01:17:18+09:00<p>서비스를 운영하려다 보니 자연히 데이터베이스 스키마를 관리할 수 있는 마이그레이션 도구가 필요했다. 현재 백엔드에 Node.js를 사용하고 있기는 하지만 마이그레이션 도구도 Node.js일 필요는 없다고 생각했다. Node.js는 데이터베이스쪽이 좀 약하다고 생각하는 편인데 데이터베이스 라이브러리도 쓸만한 게 있고 드라이버도 꽤 안정적으로 개발되고 있지만, 역사나 인구가 적다 보니 마이그레이션 도구 같은 부분은 선택의 폭이 높지 않다. 그리고 마이그레이션 도구를 애플리케이션 내에서 자동으로 돌릴 게 아니라 별로도 실행할 것이므로 Node.js에 국한하지 않고 쓸만한 도구를 찾기 시작했다.<br />
<br></p>
<h1>Alembic</h1>
<p>주변 사람들이 어떤 마이그레이션 도구를 사용하는지 수소문해서 알게 된 도구가 <a href="https://bitbucket.org/zzzeek/alembic">Alembic</a>이다. Alembic은 <a href="http://www.sqlalchemy.org/">SQLAlchemy</a> 기반의 마이그레이션 도구로 <a href="https://www.python.org/">Python</a>을 사용하지만, 별도로 사용할 수 있으므로 프로젝트가 꼭 파이썬이거나 SQLAlchemy를 사용할 필요는 없다. <a href="http://alembic.readthedocs.org/en/latest/">문서</a>도 잘 작성되어 있고 사용법이 간단해서 금새 익힐 수 있다.</p>
<p>설치는 <code>pip install alembic</code>로 간단히 설치할 수 있다. 물론 Python이나 <a href="https://pypi.python.org/pypi/pip">pip</a>는 설치되어 있어야 한다. 만약 <code>No module named psycopg2</code>라는 오류가 발생하면 <code>sudo easy_install psycopg2</code>로 설치해야 한다.<br />
<br></p>
<h2>초기화</h2>
<p>설치하면 커맨드라인에서 <code>alembic</code> 명령어를 사용할 수 있고 다음 명령어로 초기화를 할 수 있다.</p>
<pre class="line-numbers"><code class="language-bash">$ alembic init myproject
</code></pre>
<p>alembic으로 초기화를 하면 다음과 같은 파일들이 생성된다.</p>
<pre class="line-numbers"><code class="language-clike">├── alembic.ini
└── myproject
├── README
├── env.py
├── env.pyc
├── script.py.mako
└── versions
</code></pre>
<p><code>alembic.ini</code>이 설정 파일이므로 여기서 데이터베이스 설정을 할 수 있다.</p>
<pre class="line-numbers"><code class="language-clike">[alembic]
# path to migration scripts
script_location = myproject
sqlalchemy.url = driver://user:pass@localhost/dbname
...
</code></pre>
<p>위 파일에서 <code>sqlalchemy.url</code>부분에 사용하는 데이터베이스를 지정하면 된다.<br />
<br></p>
<h2>마이그레이션 관리</h2>
<p>alembic은 리비전을 사용해서 데이터베이스 스키마를 관리한다.</p>
<pre class="line-numbers"><code class="language-bash">$ alembic revision -m "create user table"
Generating /myproject/versions/2987e9c41e5e_create_user_table.py ... done
</code></pre>
<p>위처럼 새로운 리비전을 추가하면 <code>versions</code>폴더 아래 새로운 마이그래이션 파일이 생기고 이 파일은 다음과 같이 생겼다.</p>
<pre class="line-numbers"><code class="language-python">"""create user table
Revision ID: 2987e9c41e5e
Revises:
Create Date: 2015-05-10 22:10:18.235580
"""
# revision identifiers, used by Alembic.
revision = '2987e9c41e5e'
down_revision = None
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
pass
def downgrade():
pass
</code></pre>
<p><code>upgrade()</code>는 마이그래이션 버전을 적용할 때 실행되고 <code>downgrade()</code>는 적용한 마이그래이션을 취소할 때 실행된다. 처음에는 아무 동작도 하지 않게 <code>pass</code>로 되어 있으므로 여기에 테이블 추가나 칼럼변경 같은 코드를 작성해야 한다.</p>
<pre class="line-numbers"><code class="language-python">def upgrade():
op.create_table(
'users',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('name', sa.String(50), nullable=False)
)
def downgrade():
op.drop_table('account')
</code></pre>
<p>alembic이 SQLAlchemy를 사용하므로 위처럼 <code>sa</code>객체를 이용해서 마이그레이션 코드를 작성할 수 있다. 애플리케이션도 SQLAlchemy를 사용하고 있다면 이 마이그레이션 코드도 자동으로 생성하는 등의 장점이 있는 것 같은데 그렇지 않다면 직접 작성해야 한다. SQLAlchemy를 사용해 봤다면 쉽게 작성할 수 있지만, 나처럼 SQLAlchemy를 사용해 본 적이 없다면 SQLAlchemy로 코드를 작성하는 것이 좀 힘 들 수 있다.</p>
<pre class="line-numbers"><code class="language-python">def upgrade():
op.execute("""
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
name VARCHAR(50) NOT NULL
)
""")
def downgrade():
op.execute("""
DROP TABLE users
""")
</code></pre>
<p>위처럼 <code>op.execute()</code>를 사용하면 SQL을 사용할 수 있으므로 SQLAlchemy에 익숙하지 않다면 차라리 이 방법이 더 편한다.</p>
<pre class="line-numbers"><code class="language-bash">$ alembic upgrade head
INFO [alembic.migration] Context impl PostgresqlImpl.
INFO [alembic.migration] Will assume transactional DDL.
INFO [alembic.migration] Running upgrade -> 2987e9c41e5e, create user table
</code></pre>
<p>이제 <code>alembic upgrade head</code>을 실행하면 위처럼 <code>upgrade()</code>함수가 실행되어 <code>users</code> 테이블이 생성된다. 데이터베이스에는 <code>alembic_version</code>라는 테이블이 생성되고 여기서 현재 적용된 리비전을 관리하게 된다.</p>
<pre class="line-numbers"><code class="language-bash">$ alembic revision -m "add age column"
Generating /myproject/versions/4c32125f4f5a_add_age_column.py ... done
</code></pre>
<p><code>4c32125f4f5a_add_age_column.py</code> 파일을 다음과 같이 수정해서 스키마 변경을 계속 관리할 수 있다.</p>
<pre class="line-numbers"><code class="language-python">"""add age column
Revision ID: 4c32125f4f5a
Revises: 40686f5279e2
Create Date: 2015-05-11 00:20:47.794986
"""
# revision identifiers, used by Alembic.
revision = '4c32125f4f5a'
down_revision = '40686f5279e2'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
op.execute("""
ALTER TABLE users
ADD age INTEGER
""")
def downgrade():
op.execute("""
ALTER TABLE users
DROP COLUMN age
""")
</code></pre>
<p>이 파일을 보면 아까 추가한 리비전이 지정되어 있음을 알 수 있고 여기서는 <code>users</code>테이블에 새로운 칼럼을 추가했다.</p>
<pre class="line-numbers"><code class="language-bash">$ alembic upgrade head
INFO [alembic.migration] Context impl PostgresqlImpl.
INFO [alembic.migration] Will assume transactional DDL.
INFO [alembic.migration] Running upgrade 40686f5279e2 -> 4c32125f4f5a, add age column
</code></pre>
<p>이런 식으로 스키마에 변경사항이 생길 때마다 마이그레이션 파일을 추가하고 적용할 수 있으며 개발 데이터베이스나 프로덕션 데이터베이스에서도 쉽게 적용하고 관리할 수 있다.</p>
<pre class="line-numbers"><code class="language-bash">$ alembic history
40686f5279e2 -> 4c32125f4f5a (head), add age column
<base> -> 40686f5279e2, create user table
</code></pre>
<p><code>alembic history</code> 명령어를 사용하면 스키마 히스토리도 확인할 수 있다. 러닝 커브도 높지 않고 간단히 사용할 수 있어서 현재 만족하며 사용 중이다.</p>
<p><strong><a href="https://blog.outsider.ne.kr/1143?commentInput=true#entry1143WriteComment">댓글 쓰기</a></strong></p>오픈소스 MySQL 모델링 툴 :: DB DesingerOutsiderhttps://blog.outsider.ne.kr/2862009-02-11T01:27:29+09:002009-02-10T23:45:58+09:00웹사이트 작업을 하면 선행되어야 하는 것들 중 하나가 ERD이다. 다른 사람들은 어떤지 모르겠지만 보통은 ERD작업에서 대표적인 ERWin이기는 한데 워낙 비싼 녀석이고 회사는 불법소프트웨어 단속이다 머다 하면서 마땅히 해결책도 주지 않은채 ERD는 내놓아야하는 상황속에서 찾아낸 툴이 <span style="color: rgb(255, 118, 53);">DB Designer</span>라는 툴이다.(마침 프로젝트가 MySQL이기도 했다.)<br><br><div class="imageblock center" style="text-align: center; clear: both;"><img src="//blog.outsider.ne.kr/attach/1/1109207597.jpg" alt="사용자 삽입 이미지" height="296" width="332" /></div><br><a href="http://www.fabforce.net/dbdesigner4/" target="_blank">DB Designer4</a>는 <a href="http://www.fabforce.net/dbdesigner4/" target="_blank">Fabulous FORCE</a>라는 회사에서 만든 <span style="color: rgb(204, 153, 0);">모델링 툴로 MySQL에 최적화 되어서 만들어진 오픈소스 프로그램인데 다른 데이터베이스에도 사용이 가능하다. GNU GPL로 배포되고 맘대로 사용이 가능하다.</span>(작년부터는 내 개발환경의 대부분이 오픈소스화 되어가고 있는데 좋은 현상이라고 생각한다.) 이 포스팅을 하면서 알게 된 것이 DBDesigner4가 MySQL Workbench로 대체되었다는 것을 알게 되었다. 이 대체되었다는 것의 정확한 의미는 모르겠지만 설명에 보면 fabFORCE의 창립자이자 DBDesigner4의 주도적 역할을 한 Michael G.Zinner이 <a href="http://dev.mysql.com/workbench/" target="_blank">MySQL Workbench</a>를 만든 Sun Microsystems의 개발툴 팀을 이끌고 있기 때문에 <span style="color: rgb(204, 153, 0);">앞으로의 개발은 Workbench로 진행된다는 의미</span>로 보인다.(아직 Workbench는 안써봐서...)<br><br>어쨌든 DB Designer 4도 <a href="http://www.fabforce.net/dbdesigner4/downloads.php" target="_blank">다운로드 페이지</a>를 통해서 여전히 다운로드가 가능하다.(언제까지 제공할런지는 모르겠지만...)<br><br><div class="imageblock center" style="text-align: center; clear: both;"><img src="//blog.outsider.ne.kr/attach/1/1046110390.gif" alt="사용자 삽입 이미지" height="500" width="550" /></div><br>ERWin과는 좀 다르긴 하지만 처음 깔아도 약간 만져보면 크게 부담감이 없을 정도로 생겨주셨다. 일일이 설명안해도 대충 머하는 지 알수 있을 정도이다. <br><br><div class="imageblock center" style="text-align: center; clear: both;"><img src="//blog.outsider.ne.kr/attach/1/1335207607.gif" alt="사용자 삽입 이미지" height="269" width="550" /></div><br><span style="color: rgb(204, 153, 0);">[Options] - [DBDesigner Options] - [Database Options]</span>에 가면 기본적인 ERD의 데이터베이스 타입을 결정할 수 있는데 옵션에는 여러가지 데이터베이스를 설정할 수 있다고 되어 있는데 막상 바꿀려고 해도 바뀌지 않는다. 소개에도 밝혔듯이 MySQL 최적화로 되어있어서인지 <span style="color: rgb(255, 118, 53);">MySQL로만 ERD를 그릴 수 있다. DB연결해서 리버스엔지니어링해서는 다른 데이터베이스도 가능한것 같은데 기본적으로는 MySQL만 가능하다.</span> <a href="http://sourceforge.net/projects/dbdesigner-fork" target="_blank">DBDesigner Folk</a>가 DBDesigner을 다른 데이터베이스에도 사용할 수 있게 빠져나온 거라는데 해봤는데 그것도 MySQL말고는 어떻게 하는지 모르겠더라...<br><br><div class="imageblock left" style="float: left; margin-right: 10px;"><img src="//blog.outsider.ne.kr/attach/1/1189637945.gif" alt="사용자 삽입 이미지" height="126" width="35" /></div><br>메뉴는 다른건 크게 필요없고 핵심인 옆의것들만 보면 될것 같다. 맨위의 아이콘은 여러 테이블을 그룹화 해주는 Region아이콘이고 두번째가 가장 많이 쓸 테이블을 만들 아이콘이다. 그리고 아래의 3개가 1:n, 1:1, n:m의 관계를 설정해 주는 아이콘이다. <br><br><div class="imageblock center" style="text-align: center; clear: both;"><img src="//blog.outsider.ne.kr/attach/1/1103691975.gif" alt="사용자 삽입 이미지" height="425" width="550" /></div><br>디비디자이너에서 그리면 위 화면처럼 그릴 수 있다. MySQL만 된다는 건 아쉽기는 하지만 아쉬운 환경에서 ERD 모델링정도 한다는 차원에서도 충분한것 같다. 파워포인트나 손으로 그릴수는 없지 않은가... ㅎ<br><br><div class="imageblock center" style="text-align: center; clear: both;"><img src="//blog.outsider.ne.kr/attach/1/1044856762.gif" alt="사용자 삽입 이미지" height="177" width="428" /></div><br><br><span style="color: rgb(204, 153, 0);">[Display] - [Notation] </span>설정을 통해서 관계 아이콘의 다양한 설정도 가능하다. 보통은 Crows Foot이라고 되어 있는 형태를 나는 많이 쓰긴 하지만 그런거야 상황에 따라 다른거니까. 테이블에 대한 표현방식도 <span style="color: rgb(204, 153, 0);">[Display] - [Table Columns]</span>의 설정을 통해서 원하는 형태로 다양하게 표현할 수 있다. 다만<span style="color: rgb(204, 153, 0);"> ERWin처럼 논리디비와 물리디비를 같이 만들어서 바꾸어가면서 볼 수 없다는 건 무척이나 아쉬운 점이긴 하지만</span> 무료라는 점을 감안한다면 충분히 납득할 정도의 수준이라고 생각한다. 이젠 Workbench로 바뀌었다니까 다음부터는 Workbench를 써보려고 생각중....<br><p><strong><a href="https://blog.outsider.ne.kr/286?commentInput=true#entry286WriteComment">댓글 쓰기</a></strong></p>여러 행 SELECT해서 INSERT 하기Outsiderhttps://blog.outsider.ne.kr/2632009-01-06T02:02:13+09:002009-01-06T02:02:13+09:00여러 행을 가지고 한번에 인서트를 해야할 경우가 최근에 꽤 있었다. 한쪽 테이블에서 어떤 조건으로 셀렉트해서 다른쪽 테이블에 한꺼번에 넣어주기... 그렇게 흔한 상황은 아니지만 충분히 있을법한 상황이다. <br><br>처음에는 이걸 할줄 몰라서 SELECT해와서 루프돌면서 인서트를 날려줬다. 아~ 느려.. ㅡ..ㅡ 갯수가 그렇게 많지 않았으니까 다행이지.......<br><br><pre class="line-numbers"><code class="language-sql">
INSERT INTO table_a
( title, name, regdate, register, memberid, categoryid )
SELECT title, name, regdate, register, memberid, categoryid
FROM table_b
WHERE categoryid=10
</code></pre><br>위에처럼 해주면 인서트문 한방으로 수십, 수백줄의 행을 추가해 줄 수 있다. 솔직히 이거 하기 전에는 INSERT는 한번에 하나만 되는 줄 알았다. ㅋ WHERE절은 SELECT문에 딸린 조건문이다. INSERT문이 아니라.... 이렇게 SELECT로 할 때는 원래의 INSERT문에 들어가는 VALUES는 들어가지 않고 당연한 얘기로 INSERT할 컬럼수와 SELECT하는 컬럼수 및 타입이 동일해야 된다.<br><br>SQL책하나 보고 좀 감오나 했더니 복잡한 쿼리 오니까 다시 헷갈리는 구만...<br><p><strong><a href="https://blog.outsider.ne.kr/263?commentInput=true#entry263WriteComment">댓글 쓰기</a></strong></p>[Book] Head First SQL : 효율적인 DB 관리를 위한 SQL 학습법Outsiderhttps://blog.outsider.ne.kr/2592009-01-19T01:20:27+09:002008-12-29T23:48:02+09:00<div class="ttbReview">
<fieldset style="margin: 10px; padding: 5px; width: 90%;"><legend><a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8979145608&ttbkey=ttboutsideris1727002&COPYPaper=1" class="aladdin_title">Head First SQL : 효율적인 DB 관리를 위한 SQL 학습법</a></legend>
<p>
</p><table>
<tbody>
<tr>
<td><a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8979145608&ttbkey=ttboutsideris1727002&COPYPaper=1"><img src="http://image.aladdin.co.kr/cover/cover/8979145608_1.jpg" alt="" border="0"></a></td><td style="vertical-align: top;" align="left"><a href="http://www.aladdin.co.kr/shop/wproduct.aspx?ISBN=8979145608&ttbkey=ttboutsideris1727002&COPYPaper=1" class="aladdin_title">Head First SQL : 효율적인 DB 관리를 위한 SQL 학습법</a> - <img src="http://image.aladdin.co.kr/img/common/star_s8.gif" alt="8점" border="0"><br>린 베일리 지음, 박종걸 옮김/한빛미디어</td></tr></tbody></table></fieldset><br><span style="color: rgb(255, 118, 53);"><br>역시 헤드퍼스트 시리즈는 정말이지 어려운 걸 아주 쉽게 설명해주는 재주가 있다. </span>제목대로 SQL쿼리에 대한 책이다. 물론 SQL을 설명하자니 정규화라든지 디비모델링에 대해서도 설명하고 있기는 하지만 <span style="color: rgb(204, 153, 0);">대부분은 오로지 SQL쿼리에만 집중하고 있다. </span><br><br>헤드퍼스트 책을 처음 보면 초반에는시시하게 느껴질정도로 아주 기초적인 설명을 하고 있다. 이책도 마찬가지고 SELECT 조회 한번 날리는데 페이지를 몇페이지를 소비하는지 깜짝 놀랄 뿐이다. 여기서 너무 쉽다고 책을 접어버리면 나중에 후회한다. <span style="color: rgb(204, 153, 0);">SQL에서 핵심적인 내용을 아주 기가막히게 설명해준다. 특히 설명하기 쉽지 않은 정규화나, 서브쿼리, 조인 같은거는 개념 정리하기에 정말 좋다.</span><br><br>실제 웹개발을 하면 쿼리는 사용하는 쿼리만 쓰게 되고 솔직히 create같은 경우는 잘 안쓰게 된다. 물론 이것저것 복잡해 지면 다 써야되기는 하지만 GUI툴을 많이 쓰고(물론 개발할때는 쿼리짜서 넣어야 하지만.. ㅎ) 처음 테이블 만들때도 ERWIN같은 툴을 이용해서 ERD만들어서 바로 DBMS로 쏴버리기 때문에 처음부터 create해서 제약조건 걸고 타입선언해주면서 하는 경우는 극히 드물다고 생각한다.<br><br>하지만 이해는 당연히 하고 있어야 한다. 쿼리를 좀 만져본 사람이라면 어렵다 할만한 내용은 그리 많지 않다고 생각하기에 수준이 중급까지는 안된다고 생각한다. <span style="color: rgb(204, 153, 0);">초급에서 초중급정도까지? 아니면 나처럼 쿼리를 좀 막 배운 사람이 쿼리의 기초를 복습(?) 또는 정리하는 면에서는 딱 좋은것 같다. 그리고 아주 쉽게 설명되어 있어서 쿼리를 처음 배울때도 적극 추천이다.</span><br><br><br><br>헤드퍼스트책이 그렇듯이 구성도 아주 잘 되어 있다. 일반적으로 SELECT설명하고 다른쿼리 설명하고 정규화 쭉~ 설명하고, 함수들 설명하고 그런 것이 아니라 <span style="color: rgb(204, 153, 0);">어떤 문제를 해결하기 위한 점점 살붙혀나가기 식의 설명은 배우는 입장으로서는 이해하는데 큰 도움이 된다.</span> 하나 배우고 거기서의 문제점 제기하고 또 설명하고 계속 꼬리에 꼬리를 무는... 이렇게 하면 기억도 많이 남게 되는것 같다. 정규화 같은 경우도 실무에서는 교과서처럼 하진 않으니까 그냥 감으로 하곤 했는데 이 책을 통해서 좀 확실히 이해를 할 수 있었다.<br><br>그리고 <span style="color: rgb(204, 153, 0);">대부분의 쿼리는 ANSI기준으로 하고 있다.</span> 따로 ANSI라는 말은 전혀 사용하고 있지 않고 MySQL에서 최적화 되어 있다고 하지만 DBMA마다 좀 다르기 때문에 MySQL을 중점으로 설명했을뿐 쿼리는 ANSI SQL에 초점이 맞춰있고 DBMS마다 확인해 봐야하는 상황이라거나 최적화 한다는 MySQL에서는 지원하지 않는 부분등에는 꼭 체크해주고 있기 때문에 사용하는 DBMS에 신경쓰지 않고 볼 수 있다. (개인적으로 T-SQL이나 이런거 다 필요없고 그냥 ANSI에만 집중하면 된다고 생각하기에...) <br></div><p><strong><a href="https://blog.outsider.ne.kr/259?commentInput=true#entry259WriteComment">댓글 쓰기</a></strong></p>