문제

나는 결과 세트에서 많은 다른 쿼리를하려고 노력하고 있습니다. 매우 큰 창조 시간. 성능을 얻으려면 온도 테이블을 사용 하고이 온도 테이블에서 많은 쿼리를하고 싶습니다.

꽤 표준적인 것 같습니다. 그러나 나는이 온도 테이블을 동적 SQL로 공유하기 위해 고군분투하고 있습니다. 내가 이해했듯이, 각 sqlcommand 객체는 자체 스레드에서 실행되므로 온도 테이블은 다른 범위에 있으므로 쿼리 스레드에서 액세스 할 수 없습니다.

나는 글로벌 임시 테이블을 사용하려고 시도했지만 훌륭하지만 이상적이지 않습니까?

동적 SQL 쿼리간에 로컬 임시 테이블을 공유하려면 어떻게해야합니까?

내 의도 :

using (var conn = new SqlClient.SqlConnection("..."))
{
    // Creation involes many table joins in reality
    String creationScript = "SELECT * FROM FooTable INTO #MyTemp";
    SqlCommand createTempTbl = new SqlCommand(creationScript, conn);
    createTempTbl.ExecuteNonQuery();

    String query1 = "SELECT * FROM #MyTemp where id=@id";
    SqlCommand query1Comm = new SqlCommand(query1, conn);
    query1Comm.Parameters.Add("@id", ...);

    String query2 = "SELECT * FROM #MyTemp where name=@name";
    SqlCommand query2Comm = new SqlCommand(query2, conn);
    query2Comm.Parameters.Add("@name", ...);

    // And so on the queries go

} // Now want #MyTemp to be destroyed
도움이 되었습니까?

해결책

글로벌 임시 테이블을 사용해 볼 수 있습니다 (예 : 사용 ##MyTemp 보다는 #MyTemp 쿼리에서), 이 경고로:

테이블이 끝나는 세션이 테이블 종료되고 다른 모든 작업이 참조를 중지하면 글로벌 임시 테이블이 자동으로 삭제됩니다. 작업과 테이블 사이의 연관성은 단일 Transact-SQL 문의 수명에 대해서만 유지됩니다. 이는 생성 세션이 종료되었을 때 테이블을 적극적으로 참조하는 마지막 Transact-SQL 문이 완료되면 글로벌 임시 테이블이 삭제되었음을 의미합니다.


편집하다: 죄송합니다. 이미 글로벌 온도 테이블을 시도했다는 사실을 놓쳤습니다.

온도 테이블을 생성/채워진 다음 쿼리를 실행하고 여러 결과 세트를 클라이언트 코드로 반환하는 단일 저장 프로 시저로 모든 로직을 이동하는 것은 어떻습니까?

다른 팁

나는 이것이 게시 된 이래로 시간이 오래 걸린다는 것을 알고 있지만 대답은 매우 간단하다고 생각합니다.

MS Enterprise Library를 사용하여 데이터베이스에 액세스하는 것을 추측합니다. 이것은 명령 테이블이 명령 사이에 존재하지 않는 이유를 설명합니다. 명령이 완료되면 Enterprise Library는 명령이 완료되면 DB (풀에 다시 넣음)에 대한 연결을 명시 적으로 닫습니다. 즉, 명령을 거래에 넣지 않는 한. ado.net을 직접 사용하는 경우 (연결을 열고, 명령을 빌드하고 실행 한 다음 연결을 닫으면)이 문제가 발생하지 않습니다 (연결이 닫히면 귀하에게 달려 있습니다. 더 위험합니다). 다음은 MS Enterprise Library 및 거래 (죄송합니다, vb.net)를 사용하여 작성된 코드입니다.

' Get a reference to the database
Dim sqlNET As New Sql.SqlDatabase("*Your Connection String Here...*")

' Specify the transaction options
Dim oTranOpt As TransactionOptions = New TransactionOptions
' What type of isolation the transaction should have (V. Important):
oTranOpt.IsolationLevel = IsolationLevel.ReadUncommitted ' This one doesn't place locks on DB but allows dirty reads
' How long the transaction has to complete before implicitly failing (h,m,s):
oTranOpt.Timeout = New TimeSpan(0, 0, 30)

' Start the scope of the transation
Using oTranScope As TransactionScope = New TransactionScope(TransactionScopeOption.Required, oTranOpt)

    ' Create the connection to the DB. Not abs. necessary. EL will create one but best to do so.
    Using Conn As Common.DbConnection = sqlNET.CreateConnection

        ' Create a Temp Table
        sqlNET.ExecuteNonQuery(CommandType.Text, "SELECT * INTO #MyTemp FROM FooTable")

        ' Get results from table, e.g.
        Dim intCount As Integer = sqlNET.ExecuteScalar(CommandType.Text, "Select Count(*) from #MyTemp")

        MsgBox(intCount)

        ' Flag transaction as successful (causes a commit when scope is disposed)
        oTranScope.Complete()

    End Using ' Disposes the connection

End Using ' If this point is reached without hitting the oTranScope.Complete - the transaction is rolled back and locks, if any, are released.

트랜잭션 범위를 꺼내면 테이블이 더 이상 존재하지 않으므로 선택 카운트 (*)에서 코드가 실패합니다. 범위를 지정하면 명령 호출 간의 연결을 열어줍니다.

나는 이것이 누군가를 돕기를 바랍니다.

닐.

질문에서 누락 된 것은 생성 된 테이블의 수명주기입니다. 당신이 그것을 잠시 동안 붙잡고 있다면, 그것은 온도 테이블이 아니며, 그것은 당신이 채우고 사용하는 작업 테이블입니다. 나는 온도 테이블을 전혀 사용하지 않고, 선택한 사람이 선택하고 다른 모든 사람들이 떨어질 때까지 (항상) 사용하는 일반 테이블 만 사용합니다.

내가 성공적으로 사용한 대안은 tempdb에서 작업 테이블을 만들고 그것이 글로벌 임시 테이블처럼 사용하는 것입니다 (예 : "tempdb.dbo.mytable"). SQL Server가 재부팅 할 때 사용자 테이블이 삭제됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top