سؤال

أحاول أن أفعل العديد من الاستفسارات المختلفة في مجموعة النتائج التي لديها جدا وقت خلق كبير. للحصول على مكاسب الأداء، أود استخدام جدول Temp ويفعل العديد من الاستفسارات في جدول TEMP هذا.

يبدو قياسية جميلة. ومع ذلك، أنا تكافح لتبادل جدول TEMP هذا في SQL الديناميكي. كما أفهمها، ينفذ كل كائن SQLCommand في مؤشر الترابط الخاص به، وبالتالي فإن جدول TEMP موجود في نطاق مختلف - وبالتالي جعله يتعذر الوصول إليه من مؤشر ترابط الاستعلام.

حاولت استخدام طاولة مؤقتة عالمية وهذا يعمل بشكل رائع، ولكن ليس مثاليا؟

كيف يمكنني مشاركة جدول مؤقت محلي بين استعلامات 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 في استفساراتك)، مع هذا التحذير:

يتم إسقاط الجداول المؤقتة العالمية تلقائيا عند انتهاء الجلسة التي أنشأت الجدول ووقف جميع المهام الأخرى الرجوع إليها. يتم الحفاظ على الارتباط بين المهمة والجدول فقط لحياة عبارة SQL واحدة. هذا يعني أنه يتم إسقاط جدول مؤقت عالمي عند الانتهاء من آخر عبارة Transact-SQL التي كانت تشير بنشاط إلى الجدول عند انتهاء جلسة الخلق.


تعديل: عفوا، غاب عن حقيقة أنك قد حاولت بالفعل جداول TEMP العالمية.

ماذا عن نقل جميع منطقك إلى إجراء مخزن واحد يقوم بإنشاء / يملأ جدول TEMP ثم يقوم بتشغيل الاستعلامات وإرجاع نتائج متعددة إلى رمز العميل؟

نصائح أخرى

أعلم أنه بعض الوقت لأن هذا تم نشره ولكن الجواب، وأعتقد أنه بسيط للغاية.

أنا أستخدمك تستخدم مكتبة MS Enterprise للوصول إلى قاعدة البيانات، وهذا ما يفسر سبب عدم وجود جدول TEMP بين الأوامر. تغلق مكتبة المؤسسة بشكل صريح الاتصال ب DB (يضعها مرة أخرى في المسبح) عند انتهاء الأمر. وهذا هو، ما لم تضع الأوامر في معاملة. إذا كنت تستخدم ADO.NET مباشرة (عن طريق فتح الاتصال، قم ببناء الأوامر وتنفيذها، ثم إغلاق الاتصال) لا تحصل على هذه المشكلة (الأمر متروك لك عند إغلاق الاتصال - وهو أكثر خطورة). فيما يلي بعض الكود المكتوبة باستخدام مكتبة MS Enterprise والمعاملة (آسف، 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.

إذا كنت تقوم بإخراج نطاق المعاملات، فسوف يفشل الرمز على عدد المحدد (*) حيث لم يعد الجدول موجودا. تحديد النطاق يبقي الاتصال مفتوحا بين مكالمات الأوامر.

آمل أن يساعد هذا شخص ما.

نيل.

ما هو مفقود من سؤالك هو دورة حياة الجدول الذي تم إنشاؤه. إذا كان لديك إلقاء الضوء لفترة من الوقت، فهذا ليس جدول مؤقت تماما، فهو طاولة عمل تقوم بمروبتها واستخدامها. لن أستخدم جدول TEMP على الإطلاق، مجرد جدول منتظم يتم إنشاؤه بواسطة SELECT TON ومستخدمه من قبل أي شخص آخر حتى يتم إسقاطه (إن وجدت).

بديل استخدمته بنجاح هو إنشاء جدول عمل في tempdb، واستخدامه كما لو كان جدول مؤقتا (على سبيل المثال، "tempdb.dbo.mytable"). تذكر أن يتم إسقاط جداول المستخدم عند إعادة تشغيل SQL Server.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top