Web/ASP & ASP.NET2009. 4. 9. 23:13

< 출처 : korea.internet.com, 지은이 : 최현진 >

ADO의 Command 개체는 질의, SQL 문장 그리고 저장 프로시저(Stored Procedure)를 실행할 수 있는 개체이다.



[그림] Command 개체


Command 개체는 특별히 매개변수를 갖는 질의(Query) 또는 저장 프로시저를 수행할 때 보다 효과적이며, Command 개체를 이용하면, 질의를 통해서 Recordset 개체를 생성하거나, Insert, Update, Delete 같은 SQL 문장을 실행하거나, 데이터베이스의 구조를 변경하는 작업 등을 할 수 있다.

Command 개체는 다음과 같은 방법으로 선언해서 사용할 수 있다.

Dim adoCmd As ADODB.Command
Set adoCmd = New ADODB.Command

Command 개체를 사용하지 않고 Connection 개체의 Execute 메서드 또는 Recordset 개체의 Open 메서드를 사용해서 질의를 실행할 수 있다. 하지만, 질의를 계속해서 재사용하기를 원하거나, 매개변수와 함께 사용하려고 할 때에는 Command 개체를 사용하는 것이 좋다.

그럼 Command 개체의 속성과 메서드 그리고 이벤트에 대해서 자세히 살펴 본다.


Command 개체의 속성


속성 설명 기본 값 데이터 형식
ActiveConnection 상위 Connection 개체를 지정한다. (읽기/쓰기) Null 개체 Connection
CommandText 실행할 SQL 문을 지정한다. (읽기/쓰기) Zero-Length 문자열 String
CommandTimeout 명령어가 결과를 반환할 때까지 대기하는 시간을 지정한다. (초 단위) (읽기/쓰기) 30초 Long
CommandType 실행할 명령의 타입을 지정한다. adCmdUnknown CommandTypeEnum
Name Command 개체의 이름을 나타낸다. 없음 String
Prepared 명령을 실행하기 전에 컴파일 버전을 저장할지를 결정한다. (읽기/쓰기) False Boolean
Properties 데이터 Provider에 대한 프로퍼티 개체들의 컬렉션이다. (읽기 전용) 없음 Properties
State Command 개체의 상태를 나타낸다. (읽기 전용) adStateClosed Long



ActiveConnection 속성

ActiveConnection 속성은 현재의 Command 개체가 속해 있는 Connection 개체를 나타낸다. 이 속성은 연결을 위한 정보를 문자열로 지정하거나, Connection 개체를 지정할 수 있으며, 기본값은 Null 개체이다.

ActiveConnection 속성에 Nothing을 지정하면 Command 개체에 지정된 Connection 개체의 정보가 삭제되며, 데이터소스와의 연결을 위해 사용했던 자원(Resource)도 제거된다. Command 개체는 서로 다른 Connection 개체에 연결되어서 사용될 수 있다.

Command 개체의 Parameters 컬렉션이 매개변수를 포함하고 있을 경우라도, Command 개체에 Nothing을 지정하거나, 다른 Connection 개체에 Command 개체가 연결될 경우 Parameters 컬렉션은 초기화된다.

[예제]
다음 예제는 SQL 서버의 Pubs 데이터베이스에 있는 byroyalty라는 저장 프로시저를 수행하는 예이다. 로열티를 입력하라는 메시지 창이 나타나면 100을 입력해 본다.

다음 예제에서는 Connection 개체와 Command 개체의 관계에 대한 부분만을 제대로 이해하면 되며, 코드의 나머지 부분들에 대해서는 이 절의 이어지는 내용에서 자세히 다루고 있다.

Private Sub cmdActiveConnection_Click()
  Dim adoCn As New ADODB.Connection
  Dim adoCmd As New ADODB.Command
  Dim adoPara As New ADODB.Parameter
  Dim adoRs As New ADODB.Recordset
  Dim iRoyalty As Integer
  Dim strAuthorID As String
  Dim strConn As String

  strConn = "Provider=sqloledb;Data Source=(local);Initial Catalog=Pubs;User ID=sa;Password=;"
  adoCn.Open strConn

  Set adoCmd.ActiveConnection = adoCn
  adoCmd.CommandText = "byroyalty"
  adoCmd.CommandType = adCmdStoredProc
  adoCmd.CommandTimeout = 15

  '저장 프로시저의 매개변수 값을 입력 받는다.
  iRoyalty = Trim(InputBox("royalty 입력:"))

  adoPara.Type = adInteger
  adoPara.Direction = adParamInput
  adoPara.Value = iRoyalty
  adoCmd.Parameters.Append adoPara

  '명령을 실행해서 Recordset 생성
  Set adoRs = adoCmd.Execute()

  Do While Not adoRs.EOF
    Debug.Print , adoRs!au_id & vbNewLine

    adoRs.MoveNext
  Loop

  adoRs.Close
  Set adoRs = Nothing

  Set adoCmd = Nothing

  adoCn.Close
  Set adoCn = Nothing
End Sub


CommandText 속성

CommandText 속성은 Provider를 통해서 실행할 명령어(SQL 문장, 테이블 명, 저장 프로시저 명)를 지정하는 속성이며 기본값은 길이가 없는 문자열이다.

ActiveConnection 속성의 예제에서 다음과 같은 코드를 볼 수 있다.

adoCmd.CommandText = "byroyalty"

위의 코드는 Pubs 데이터베이스의 byroyalty라는 저장 프로시저를 Command 개체를 사용해서 수행하기 위해 지정하는 예이며, 위의 코드와 같은 방식으로 SQL 문장, 테이블 명, 저장 프로시저 명을 지정해서 사용할 수 있다.


CommandTimeout 속성

CommandTimeout 속성은 명령어가 결과를 반환할 때까지 대기하는 시간을 나타내며, 디폴트 값은 30초 이다. CommandTimeout 속성은 네트워크의 환경을 고려해서 명령어가 충분히 실행될 수 있는 시간을 지정하는 것이 좋으며, 0으로 설정할 경우에는 무한대로 결과를 기다리게 되며, 특별한 경우가 아니라면 디폴트 값을 사용하는 것이 좋다.

Connection 개체에도 CommandTimeout 속성이 있지만 Command 개체의 CommandTimeout 속성과는 아무런 관계가 없다. 이유는 Command 개체의 CommandTimeout 속성은 Connection 개체의 CommandTimeout 속성으로부터 상속받는 값이 아니고 독자적으로 존재하는 것이기 때문이다.

ActiveConnection 속성의 예제에서 다음과 같은 코드를 볼 수 있다.

adoCmd.CommandTimeout = 15

위의 코드는 Command 개체가 실행한 후에 15초 내에 결과가 반환되지 않으면 오류를 발생시키도록 설정하는 것이다.

특히 대량의 작업을 수행하는 저장 프로시저를 호출하는 경우라면 일반적으로 180초 정도까지는 지정한다. 이런 특별한 경우가 없다면 디폴트 값(30초)을 사용하는 것이 무난하다.


CommandType 속성

CommandType 속성은 Command 개체의 형식을 나타내며, 다음 표의 값을 지정할 수 있다.


상수 설명
adCmdUnspecified -1 CommandType 인수를 지정하지 않는다.
adCmdUnknown 8 디폴트 값, Command 개체의 타입을 알 수 없음으로 지정한다.
adCmdText 1 명령어 또는 저장 프로시저를 텍스트로 지정한다.
adCmdTable 2 테이블을 지정한다(내부적으로 생성된 SQL 문장에 의해서 필드가 생성된다).
adCmdStoredProc 4 저장 프로시저를 지정한다.
adCmdFile 256 Persisted Recordset 개체의 파일명을 지정한다.
adCmdTableDirect 512 테이블을 지정한다(모든 필드가 생성된다).


CommandType 속성의 값이 디폴트 값인 adCmdUnknown일 경우에는 CommandText 속성이 SQL 문장인지, 저장 프로시저인지, 테이블의 이름인지를 결정하기 위해서 ADO는 Provider를 호출하게 되고, CommandType 속성을 정확하게 지정한 경우 보다 Command 개체가 수행하기 위해 부하가 더 걸리게 된다.

그렇기 때문에 CommandType 속성을 정확하게 지정하고 사용하면 디폴트 값을 사용하는 것보다 빠른 속도로 명령을 실행하게 된다.

CommandType 속성에 지정한 값과 실제 실행에 사용될 명령의 형식이 맞지 않을 경우에는 Execte 메서드를 사용할 때 오류가 발생하게 된다.

Execute 메서드를 사용할 때 함께 사용할 수 있는 옵션으로 adExecuteNoRecords가 있다. 이 옵션은 명령 또는 저장 프로시저가 반환 값을 가지지 않을 경우에 지정한다.

adExecuteNoRecords 상수는 최소한의 내부 프로세스만을 거치기 때문에 속도는 빠른 반면에 항상 adCmdText 또는 adCmdStoredProc 상수와 함께 사용해야 한다.

[예제]
다음 예제는 CommandType 속성을 adCmdText로 지정해서 Command 개체를 수행하는 예이다.

Private Sub cmdCommandType_Click()
  Dim adoCn As New ADODB.Connection
  Dim adoCmd As New ADODB.Command
  Dim strConn As String

  strConn = "Provider=sqloledb;Data Source=(local);Initial Catalog=Pubs;User ID=sa;Password=;"
  adoCn.Open strConn

  Set adoCmd.ActiveConnection = adoCn
  adoCmd.CommandText = "Update Authors Set au_lname = 'Chris' Where au_id = '172-32-1176'"
  adoCmd.CommandType = adCmdText
  adoCmd.Execute

  Set adoCmd = Nothing

  adoCn.Close
  Set adoCn = Nothing
End Sub


Name 속성

Name 속성은 Command 개체의 이름을 나타낸다. 이 속성은 일반적으로 사용되지 않지만, Command 개체들의 컬렉션에서 개체를 식별하기 위해서 사용될 수 있다.

Name 속성의 값은 String이며, 다음의 코드와 같이 사용할 수 있다.
Dim adoCmd As New Command
Dim strCmdName As String

strCmdName = adoCmd.Name
adoCmd.Name = strCmdName


Prepared 속성

Prepared 속성은 실행 전에 명령의 컴파일된 버전을 Provider가 저장할 것인지를 지정하는 속성이다. Prepared 속성을 True로 설정하게 되면, Command 개체가 처음 실행하기 전에 CommandText 속성에 지정된 명령을 컴파일해서 저장하게 된다. 그렇기 때문에 처음 실행 시에는 속도가 좀 떨어지지만, 두 번째 이후의 실행부터는 컴파일 시간이 단축되기 때문에 속도가 빨라지게 된다. 이 속성은 마치 저장 프로시저를 사용하는 것과 동일한 개념이라고 볼 수 있다.

이 프로퍼티가 False 일 경우에 Provider는 명령의 컴파일 버전을 생성하지 않고 직접 실행하게 된다. Provider가 이 기능을 지원하지 않는다면, Prepared 프로퍼티를 True로 지정했을 때에는 오류가 발생한다. 만약 오류가 발생하지 않는다면 Provider가 자동으로 False로 지정한 것이다.

참고

클라이언트에서 데이터베이스로 SQL 문장의 실행을 요청하게 되면 그 SQL 문장은 다음의 4단계에 걸쳐서 수행하게 된다.
  1. 구문 검사(Syntax Check)
  2. 구문 분석(Parsing)
  3. 컴파일(Complie)
  4. 실행(Execution)

저장 프로시저를 사용하면, 컴파일까지 된 상태에서 실행을 대기하고 있기 때문에 SQL 문장을 직접 실행할 때보다 빠르게 수행하는 것이다. 반복해서 SQL 문장을 호출할 때 Prepared 속성을 사용하면, 첫번째 실행에서 저장 프로시저처럼 만든 다음 계속해서 컴파일된 SQL 문장을 사용하는 것이다.


[예제]
다음 예제는 두 개의 Command 개체를 만든 다음, 하나는 Prepared 속성을 False로 다른 하나는 Prepared 속성을 True로 설정해서 동일한 SQL 문장을 20회 수행한 후에 작업에 소요된 시간을 비교해서 Msgbox로 보여주는 예이다.

Private Sub cmdPrepared_Click()
  Dim adoCn As New ADODB.Connection
  Dim adoCmd1 As New ADODB.Command
  Dim adoCmd2 As New ADODB.Command
  Dim strConn As String
  Dim strCmd As String
  Dim sngStart As Single
  Dim sngEnd As Single
  Dim sngNotPrepared As Single
  Dim sngPrepared As Single
  Dim i As Integer

  'Connection 연결
  strConn = "Provider=sqloledb;Data Source=(local);Initial Catalog=Pubs;User Id=sa;Password=;"
  adoCn.Open strConn

  '두개의 Command 개체 생성
  '하나는 Prepared로 다른 하나는 Not Prepared로 지정
  strCmd = "SELECT Title, Type FROM Titles ORDER BY Type"

  Set adoCmd1.ActiveConnection = adoCn
  adoCmd1.CommandText = strCmd

  Set adoCmd2.ActiveConnection = adoCn
  adoCmd2.CommandText = strCmd
  adoCmd2.Prepared = True

  'Command를 20회 Execute한 시간을 계산(Not Prepared)
  sngStart = Timer
  For i = 1 To 20
    adoCmd1.Execute
  Next i
  sngEnd = Timer
  sngNotPrepared = sngEnd - sngStart

  'Commad를 20회 Execute한 시간을 계산(Prepared)
  sngStart = Timer
  For i = 1 To 20
    adoCmd2.Execute
  Next i
  sngEnd = Timer
  sngPrepared = sngEnd - sngStart

  '실행 결과
  MsgBox "실행 결과:" & vbCr & _
    " Not Prepared: " & Format(sngNotPrepared, "##0.000") & " 초" & vbCrLf & _
    " Prepared: " & Format(sngPrepared, "##0.000") & " 초"

  adoCn.Close
  Set adoCn = Nothing
End Sub


Properties 속성

데이터 Provider에 대한 속성 개체들의 컬렉션으로 읽기 전용이다.

[예제]
다음 예제는 Properties 컬렉션이 가지고 있는 값들을 보여주는 예이다.
Private Sub cmdProperties_Click()
  Dim adoCn As New ADODB.Connection
  Dim adoCmd As New ADODB.Command
  Dim strConn As String
  Dim strCmd As String
  Dim i As Integer

  strConn = "Provider=sqloledb;Data Source=(local);Initial Catalog=Pubs;User Id=sa;Password=;"
  adoCn.Open strConn

  strCmd = "SELECT Title, Type FROM Titles ORDER BY Type"

  Set adoCmd.ActiveConnection = adoCn
  adoCmd.CommandText = strCmd

  For i = 0 To adoCmd.Properties.Count - 1
    Debug.Print adoCmd.Properties(i).Name & " : "; adoCmd.Properties(i).Value
  Next i

  adoCn.Close
  Set adoCn = Nothing
End Sub

위의 예제의 결과는 다음과 같다.

  IAccessor : True
  IColumnsInfo : True
  IColumnsRowset : True
  IConnectionPointContainer : False
  IConvertType : True
  IMultipleResults : False
  IRowset : True
  IRowsetChange : False
  IRowsetIdentity : True
  IRowsetInfo : True
  IRowsetLocate : False
  IRowsetResynch : False
  IRowsetScroll : False
  IRowsetUpdate : False
  ISupportErrorInfo : True
  ISequentialStream : True
  Preserve on Abort : False
  Access Order : 2
  Blocking Storage Objects : True
  Bookmark Information : 0
  Use Bookmarks : False
  Skip Deleted Bookmarks : False
  Bookmark Type : 1
  Fetch Backwards : False
  Hold Rows : False
  Scroll Backwards : False
  Change Inserted Rows : False
  Column Privileges : False
  Command Time Out : 30
  Preserve on Commit : False
  Defer Column : False
  Delay Storage Object Updates : False
  Immobile Rows : True
  Literal Bookmarks : False
  Literal Row Identity : True
  Lock Mode : 1
  Maximum Open Rows : 0
  Maximum Pending Rows : 0
  Maximum Rows : 0
  Notification Granularity : 1
  Notification Phases : 31
  Column Set Notification : 3
  Row Delete Notification : 3
  Row First Change Notification : 3
  Row Insert Notification : 3
  Row Resynchronization Notification : 3
  Rowset Release Notification : 3
  Rowset Fetch Position Change Notification : 3
  Row Undo Change Notification : 3
  Row Undo Delete Notification : 3
  Row Undo Insert Notification : 3
  Row Update Notification : 3
  Others' Inserts Visible : False
  Others' Changes Visible : False
  Own Inserts Visible : False
  Own Changes Visible : False
  Quick Restart : False
  Reentrant Events : True
  Remove Deleted Rows : False
  Report Multiple Changes : False
  Return Pending Inserts : False
  Row Privileges : True
  Row Threading Model : 1
  Server Cursor : False
  Server Data on Insert : False
  Strong Row Identity : False
  Objects Transacted : False
  Unique Rows : False
  Updatability : 0
  Maximum BLOB Length : 0
  Fastload Options :
  Keep Nulls : False
  Keep Identity : False
  Bookmarkable : False



State 속성

State 속성은 Command 개체가 데이터 소스에 연결된 상태인지, 연결이 되지 않은 상태인지, 또는 명령을 수행 중인지를 나타내는 속성이다.


상수 설명
adStateClosed Command 개체가 데이터 소스에 연결되지 않은 상태는 나타내는 값이다.
adStateOpen Command 개체가 데이터 소스에 연결된 상태를 나타내는 값이다.
adStateExecuting Command 개체가 명령을 실행하고 있는 상태를 나타내는 값이다.
adStateFetching Recordset 개체의 레코드를 가져오고 있는 상태(Fetch)를 나타내는 값이다.


State 속성은 Command 개체를 사용하고자 하는 특정한 때에 Command 개체의 상태를 알고자 할 때 사용할 수 있다. 이 값은 읽기 전용이다.

이 속성은 Connection 개체와 Recordset 개체에도 있으며, Recordset 개체에서는 두 개 이상의 값이 조합되어 사용되기도 한다. 예를 들어, adStateOpen 값과 adStateExecuting이 조합되어 Recordset 개체의 상태를 나타내기도 한다.

이 속성은 비동기적으로 명령을 수행할 때, 명령이 아직도 수행 중인지를 평가하기 위해서 사용될 수 있다.

[예제]
다음 예제는 비동기적으로 명령을 수행한 다음, 명령이 아직 수행 중인지를 평가하는 예이다.

Private Sub cmdState_Click()
  Dim adoCn As New ADODB.Connection
  Dim adoCmd As New ADODB.Command
  Dim strConn As String
  Dim i As Integer

  strConn = "Provider=sqloledb;Data Source=(local);Initial Catalog=Pubs;User Id=sa;Password=;"
  adoCn.Open strConn

  Set adoCmd.ActiveConnection = adoCn
  adoCmd.CommandText = "SELECT Title, Type FROM Titles ORDER BY Type"
  adoCmd.Execute , , adAsyncExecute

  '명령이 아직 수행 중인지를 체크한다.
  If adoCmd.State = adStateExecuting Then
    Debug.Print "수행 중..."
  Else
    Debug.Print "수행 완료..."
  End If

  adoCn.Close
  Set adoCn = Nothing
End Sub
Posted by Huikyun