ขั้นตอนการจัดเก็บฐานข้อมูลด้วย“ โหมดแสดงตัวอย่าง”


15

รูปแบบที่พบบ่อยพอสมควรในแอปพลิเคชันฐานข้อมูลที่ฉันทำงานด้วยคือต้องสร้างขั้นตอนการจัดเก็บสำหรับรายงานหรือยูทิลิตี้ที่มี "โหมดตัวอย่าง" เมื่อโพรซีเดอร์ดังกล่าวทำการอัพเดตพารามิเตอร์นี้บ่งชี้ว่าผลลัพธ์ของแอ็คชันควรถูกส่งคืน แต่โพรซีเดอร์ไม่ควรทำการอัพเดตกับฐานข้อมูล

วิธีหนึ่งในการทำสิ่งนี้ให้สำเร็จคือการเขียนifคำสั่งสำหรับพารามิเตอร์และมีโค้ดบล็อกที่สมบูรณ์สองบล็อก หนึ่งในนั้นจะปรับปรุงและส่งคืนข้อมูลและอื่น ๆ เพียงแค่ส่งคืนข้อมูล แต่สิ่งนี้ไม่เป็นที่พึงปรารถนาเนื่องจากการทำสำเนารหัสและความเชื่อมั่นค่อนข้างต่ำว่าข้อมูลตัวอย่างเป็นภาพสะท้อนที่ถูกต้องแม่นยำว่าจะเกิดอะไรขึ้นกับการอัปเดต

ตัวอย่างต่อไปนี้พยายามใช้ประโยชน์จากจุดบันทึกและตัวแปรของการทำธุรกรรม (ซึ่งไม่ได้รับผลกระทบจากธุรกรรมตรงกันข้ามกับตาราง temp ซึ่งเป็น) เพื่อใช้รหัสบล็อกเดียวสำหรับโหมดแสดงตัวอย่างเป็นโหมดการอัปเดตสด

หมายเหตุ: การย้อนกลับของธุรกรรมไม่ใช่ตัวเลือกเนื่องจากการเรียกขั้นตอนนี้อาจซ้อนอยู่ในธุรกรรม นี่คือการทดสอบใน SQL Server 2012

CREATE TABLE dbo.user_table (a int);
GO

CREATE PROCEDURE [dbo].[PREVIEW_EXAMPLE] (
  @preview char(1) = 'Y'
) AS

CREATE TABLE #dataset_to_return (a int);

BEGIN TRANSACTION; -- preview mode required infrastructure
  DECLARE @output_to_return TABLE (a int);
  SAVE TRANSACTION savepoint;

  -- do stuff here
  INSERT INTO dbo.user_table (a)
    OUTPUT inserted.a INTO @output_to_return (a)
    VALUES (42);

  -- catch preview mode
  IF @preview = 'Y'
    ROLLBACK TRANSACTION savepoint;

  -- save output to temp table if used for return data
  INSERT INTO #dataset_to_return (a)
  SELECT a FROM @output_to_return;
COMMIT TRANSACTION;

SELECT a AS proc_return_data FROM #dataset_to_return;
RETURN 0;
GO

-- Examples
EXEC dbo.PREVIEW_EXAMPLE @preview = 'Y';
SELECT a AS user_table_after_preview_mode FROM user_table;

EXEC dbo.PREVIEW_EXAMPLE @preview = 'N';
SELECT a AS user_table_after_live_mode FROM user_table;

-- Cleanup
DROP TABLE dbo.user_table;
DROP PROCEDURE dbo.PREVIEW_EXAMPLE;
GO

ฉันกำลังมองหาข้อเสนอแนะเกี่ยวกับรหัสและรูปแบบการออกแบบนี้และ / หรือหากวิธีแก้ไขปัญหาอื่น ๆ มีอยู่ในรูปแบบที่แตกต่างกัน

คำตอบ:


12

วิธีการนี้มีข้อบกพร่องหลายประการ:

  1. คำว่า "ดูตัวอย่าง" อาจทำให้เข้าใจผิดได้ในกรณีส่วนใหญ่ขึ้นอยู่กับลักษณะของข้อมูลที่ดำเนินการอยู่ (และการเปลี่ยนแปลงนั้นจากการดำเนินการไปสู่การปฏิบัติงาน) อะไรคือการทำให้มั่นใจว่าข้อมูลปัจจุบันที่กำลังดำเนินการอยู่จะอยู่ในสถานะเดียวกันในช่วงเวลาที่มีการรวบรวมข้อมูล "ตัวอย่าง" และเมื่อผู้ใช้กลับมาอีก 15 นาทีหลังจากนั้น - หลังจากคว้ากาแฟบางส่วนออกไปข้างนอกเพื่อสูบบุหรี่ รอบ ๆ บล็อกกลับเข้ามาและตรวจสอบบางสิ่งบนอีเบย์ - และตระหนักดีว่าพวกเขาไม่ได้คลิกปุ่ม "ตกลง" เพื่อทำการดำเนินการจริงและในที่สุดก็คลิกปุ่ม?

    คุณมีเวลา จำกัด ในการดำเนินการต่อหลังจากสร้างตัวอย่างแล้วหรือไม่? หรืออาจเป็นวิธีที่จะตรวจสอบว่าข้อมูลอยู่ในสถานะเดียวกันที่เวลาการแก้ไขเหมือนเดิมSELECTหรือไม่?

  2. นี่เป็นประเด็นย่อยเนื่องจากโค้ดตัวอย่างอาจเกิดขึ้นอย่างเร่งรีบและไม่ได้เป็นตัวแทนของการใช้งานจริง แต่ทำไมจะมี "ตัวอย่าง" สำหรับการINSERTดำเนินการ ซึ่งอาจสมเหตุสมผลเมื่อแทรกหลายแถวผ่านสิ่งที่ชอบINSERT...SELECTและอาจมีจำนวนตัวแปรที่ใส่เข้าไป แต่สิ่งนี้ไม่สมเหตุสมผลเลยสำหรับการทำงานแบบซิงเกิล

  3. สิ่งนี้เป็นสิ่งที่ไม่พึงประสงค์เนื่องจาก ... มีความเชื่อมั่นค่อนข้างต่ำว่าข้อมูลตัวอย่างเป็นภาพสะท้อนที่ถูกต้องแม่นยำว่าจะเกิดอะไรขึ้นกับการอัปเดต

    "ความมั่นใจในระดับต่ำ" นี้มาจากไหน? แม้ว่าจะเป็นไปได้ที่จะอัปเดตจำนวนแถวที่แตกต่างจากที่แสดงสำหรับSELECTเมื่อมีการเข้าร่วมหลายตารางและมีการทำซ้ำแถวในชุดผลลัพธ์ซึ่งไม่ควรเป็นปัญหาที่นี่ แถวใด ๆ ที่ควรได้รับผลกระทบจากแถวUPDATEสามารถเลือกได้ด้วยตัวเอง หากมีความไม่ตรงกันคุณจะทำแบบสอบถามไม่ถูกต้อง

    และสถานการณ์เหล่านั้นที่มีการทำซ้ำเนื่องจากตารางที่เข้าร่วมที่ตรงกับหลายแถวในตารางที่จะมีการอัปเดตไม่ใช่สถานการณ์ที่จะสร้าง "ตัวอย่าง" และหากมีโอกาสที่เป็นกรณีนี้จะต้องมีการอธิบายให้ผู้ใช้ทราบว่าพวกเขาได้รับการปรับปรุงส่วนย่อยของรายงานที่ทำซ้ำภายในรายงานเพื่อที่ว่าจะไม่ปรากฏว่ามีข้อผิดพลาดหากมีใครบางคนเท่านั้น ดูจำนวนแถวที่ได้รับผลกระทบ

  4. เพื่อความสมบูรณ์ (แม้ว่าคำตอบอื่น ๆ ที่กล่าวถึงนี้) คุณไม่ได้ใช้TRY...CATCHโครงสร้างดังนั้นอาจพบปัญหาได้อย่างง่ายดายเมื่อวางสายเหล่านี้ (แม้ว่าจะไม่ได้ใช้บันทึกคะแนนและแม้ว่าจะไม่ใช้ธุรกรรมก็ตาม) โปรดดูคำตอบของฉันสำหรับคำถามต่อไปนี้ที่นี่ที่ DBA.SE สำหรับเทมเพลตที่จัดการธุรกรรมข้ามการเรียกกระบวนงานที่เก็บซ้อน:

    เราจำเป็นต้องจัดการธุรกรรมในรหัส C # หรือในขั้นตอนการจัดเก็บ

  5. แม้ในกรณีที่มีการกล่าวถึงปัญหาข้างต้นก็ยังมีข้อบกพร่องที่สำคัญอยู่: สำหรับช่วงเวลาสั้น ๆ ที่มีการดำเนินการ (เช่นก่อนหน้าROLLBACK) แบบสอบถามที่อ่านสกปรก (แบบสอบถามที่ใช้WITH (NOLOCK)หรือSET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED) สามารถดึงข้อมูลที่ ไม่ได้มีในภายหลัง ในขณะที่ทุกคนที่ใช้คำสั่งสกปรกอ่านแล้วควรจะตระหนักถึงเรื่องนี้และได้รับการยอมรับว่าเป็นไปได้การดำเนินการเช่นนี้ช่วยเพิ่มโอกาสของการแนะนำความผิดปกติของข้อมูลที่มีมากยากที่จะแก้ปัญหา (หมายถึง: วิธีการมากเวลาที่คุณต้องการที่จะใช้ความพยายามที่จะ พบปัญหาที่ไม่มีสาเหตุโดยตรงหรือไม่?)

  6. รูปแบบเช่นนี้ยังลดประสิทธิภาพของระบบโดยเพิ่มการบล็อกโดยการล็อคเพิ่มเติมและสร้างกิจกรรมการทำธุรกรรมมากขึ้น (ฉันเห็นแล้วว่า @MartinSmith ยังกล่าวถึงปัญหาทั้งสองนี้ในความคิดเห็นเกี่ยวกับคำถาม)

    นอกจากนี้หากมีทริกเกอร์ในตารางที่กำลังแก้ไขนั่นอาจเป็นการประมวลผลเพิ่มเติมเล็กน้อย (การอ่าน CPU และ Physical / Logical) ที่ไม่จำเป็น ทริกเกอร์จะเพิ่มโอกาสของความผิดปกติของข้อมูลที่เกิดจากการอ่านที่สกปรก

  7. เกี่ยวข้องกับประเด็นที่ระบุไว้ข้างต้นโดยตรง - ล็อคเพิ่มขึ้น - การใช้ธุรกรรมเพิ่มโอกาสในการหยุดชะงักโดยเฉพาะอย่างยิ่งหากมีการเรียกใช้ทริกเกอร์

  8. ปัญหาที่รุนแรงน้อยกว่าที่ควรจะเกี่ยวข้องเฉพาะกับสถานการณ์น้อยที่มีแนวโน้มของINSERTการดำเนินงาน: ความ "Preview" ข้อมูลที่อาจจะไม่เป็นเช่นเดียวกับสิ่งที่ถูกแทรกด้วยการไปถึงค่าในคอลัมน์กำหนดโดยDEFAULTจำกัด ( Sequences/ NEWID()/ NEWSEQUENTIALID()) IDENTITYและ

  9. ไม่จำเป็นต้องมีค่าใช้จ่ายเพิ่มเติมในการเขียนเนื้อหาของตัวแปรในตารางลงในตารางชั่วคราว การเปลี่ยนแปลงROLLBACKจะไม่ส่งผลต่อข้อมูลใน Table Variable (ซึ่งเป็นสาเหตุที่คุณบอกว่าคุณใช้ Table Variables ในตอนแรก) ดังนั้นมันจะทำให้รู้สึกถึงความเรียบง่ายกว่าSELECT FROM @output_to_return;ในตอนท้ายจากนั้นไม่ต้องสร้างชั่วคราว โต๊ะ.

  10. ในกรณีที่ไม่ทราบความแตกต่างของจุดบันทึกนี้ (เป็นการยากที่จะบอกได้จากตัวอย่างรหัสเพราะมันแสดงขั้นตอนการจัดเก็บเพียงครั้งเดียวเท่านั้น): คุณต้องใช้ชื่อจุดบันทึกเฉพาะเพื่อให้การROLLBACK {save_point_name}ดำเนินการทำงานตามที่คุณต้องการ หากคุณใช้ชื่ออีกครั้ง ROLLBACK จะย้อนกลับไปยังจุดบันทึกล่าสุดของชื่อนั้นซึ่งอาจจะไม่อยู่ในระดับเดียวกับที่ROLLBACKเรียกใช้งาน โปรดดูตัวอย่างรหัสบล็อกแรกในคำตอบต่อไปนี้เพื่อดูการทำงานนี้: การทำธุรกรรมในขั้นตอนการจัดเก็บ

สิ่งที่เกิดขึ้นคือ:

  • การทำ "ตัวอย่าง" ไม่เหมาะสมกับการใช้งานของผู้ใช้ ฉันทำสิ่งนี้บ่อยครั้งสำหรับการดำเนินการบำรุงรักษาเพื่อให้ฉันสามารถเห็นสิ่งที่จะถูกลบ / การรวบรวมขยะถ้าฉันดำเนินการต่อไป ฉันจะเพิ่มพารามิเตอร์ที่เรียกว่า@TestModeและทำIFคำสั่งอย่างใดอย่างหนึ่งไม่ได้SELECTเมื่ออื่นมันไม่@TestMode = 1 DELETEบางครั้งฉันเพิ่ม@TestModeพารามิเตอร์ลงในกระบวนงานที่เก็บไว้ที่เรียกใช้โดยแอปพลิเคชันเพื่อให้ฉัน (และอื่น ๆ ) สามารถทำการทดสอบอย่างง่ายโดยไม่ส่งผลกระทบต่อสถานะของข้อมูล แต่แอปพลิเคชันไม่เคยใช้พารามิเตอร์นี้

  • ในกรณีที่นี่ไม่ชัดเจนจากส่วนบนของ "ปัญหา":

    หากคุณต้องการ / ต้องการโหมด "ดูตัวอย่าง" / "ทดสอบ" เพื่อดูสิ่งที่ควรได้รับผลกระทบหากมีการดำเนินการคำสั่ง DML อย่าใช้ธุรกรรม (เช่นBEGIN TRAN...ROLLBACKรูปแบบ) เพื่อทำสิ่งนี้ให้สำเร็จ มันเป็นรูปแบบที่ดีที่สุดเพียงใช้งานได้จริงบนระบบผู้ใช้คนเดียวและไม่ใช่ความคิดที่ดีในสถานการณ์นั้น

  • การทำซ้ำแบบสอบถามจำนวนมากระหว่างสองสาขาของIFคำสั่งจะแสดงปัญหาที่อาจเกิดขึ้นจากการจำเป็นต้องอัปเดตทั้งคู่ในแต่ละครั้งที่มีการเปลี่ยนแปลง อย่างไรก็ตามความแตกต่างระหว่างสองคำสั่งมักจะง่ายพอที่จะตรวจสอบโค้ดและแก้ไขได้ง่าย ในทางตรงกันข้ามปัญหาเช่นความแตกต่างของรัฐและการอ่านที่สกปรกนั้นยากที่จะค้นหาและแก้ไขได้ยากกว่ามาก และปัญหาของประสิทธิภาพของระบบลดลงเป็นไปไม่ได้ที่จะแก้ไข เราจำเป็นต้องรู้จักและยอมรับว่า SQL ไม่ใช่ภาษาเชิงวัตถุและการห่อหุ้ม / ลดรหัสที่ซ้ำกันนั้นไม่ใช่เป้าหมายการออกแบบของ SQL เหมือนกับที่เคยเป็นกับภาษาอื่น ๆ

    ถ้าแบบสอบถามมีความยาว / ซับซ้อนเพียงพอคุณสามารถใส่แค็ปซูลเข้าไปในฟังก์ชันที่มีค่าตารางแบบอินไลน์ จากนั้นคุณสามารถทำได้ง่ายSELECT * FROM dbo.MyTVF(params);สำหรับโหมด "ดูตัวอย่าง" และเข้าร่วมกับค่าคีย์สำหรับโหมด "ทำมัน" ตัวอย่างเช่น:

    UPDATE tab
    SET    tab.Col2 = tvf.ColB
           ...
    FROM   dbo.Table tab
    INNER JOIN dbo.MyTVF(params) tvf
            ON tvf.ColA = tab.Col1;
  • หากนี่เป็นสถานการณ์รายงานตามที่คุณกล่าวถึงอาจเป็นไปได้ว่าการเรียกใช้รายงานเริ่มต้นคือ "ดูตัวอย่าง" หากมีคนต้องการเปลี่ยนบางสิ่งบางอย่างที่พวกเขาเห็นในรายงาน (อาจเป็นสถานะ) นั่นไม่จำเป็นต้องมีการแสดงตัวอย่างเพิ่มเติมเนื่องจากความคาดหวังคือการเปลี่ยนข้อมูลที่แสดงในปัจจุบัน

    หากการดำเนินการคือการเปลี่ยนแปลงจำนวนการเสนอราคาโดยกฎ% หรือกฎทางธุรกิจนั้นจะสามารถจัดการในเลเยอร์การนำเสนอ (JavaScript?)

  • หากคุณจำเป็นต้องทำการ "ดูตัวอย่าง" สำหรับการดำเนินการแบบผู้ใช้ปลายทางคุณต้องจับภาพสถานะของข้อมูลก่อน (อาจเป็นการแฮชของฟิลด์ทั้งหมดในชุดผลลัพธ์สำหรับUPDATEการดำเนินการหรือค่าคีย์สำหรับDELETEการดำเนินงาน) และจากนั้นก่อนดำเนินการเปรียบเทียบข้อมูลสถานะที่จับกับข้อมูลปัจจุบัน - ภายในธุรกรรมที่ทำHOLDล็อกบนโต๊ะเพื่อไม่ให้มีอะไรเปลี่ยนแปลงหลังจากทำการเปรียบเทียบนี้ - และหากมีความแตกต่างใด ๆ ข้อผิดพลาดและทำROLLBACKมากกว่าการดำเนินการหรือUPDATEDELETE

    สำหรับการตรวจสอบความแตกต่างสำหรับUPDATEการดำเนินงานทางเลือกในการคำนวณกัญชาในช่องที่เกี่ยวข้องจะมีการเพิ่มคอลัมน์ประเภทROWVERSION ค่าROWVERSIONประเภทข้อมูลจะเปลี่ยนโดยอัตโนมัติทุกครั้งที่มีการเปลี่ยนแปลงแถวนั้น หากคุณมีคอลัมน์ดังกล่าวคุณจะต้องSELECTไปพร้อมกับข้อมูล "ดูตัวอย่าง" อื่น ๆ แล้วส่งต่อไปยัง "แน่นอนไปข้างหน้าและทำตามขั้นตอนการอัปเดต" พร้อมกับค่าคีย์และค่า (s) เพื่อเปลี่ยน. จากนั้นคุณจะเปรียบเทียบROWVERSIONค่าที่ส่งผ่านจาก "ดูตัวอย่าง" กับค่าปัจจุบัน (ต่อแต่ละคีย์) และดำเนินการต่อด้วยUPDATEถ้าALLของค่าที่ตรงกัน ประโยชน์ที่ได้รับที่นี่คือคุณไม่จำเป็นต้องคำนวณแฮชที่มีศักยภาพแม้ว่าจะไม่น่าเป็นไปได้สำหรับเชิงลบและใช้เวลาพอสมควรในแต่ละครั้งที่คุณทำเช่นSELECTนั้น ในทางกลับกันROWVERSIONค่าจะเพิ่มขึ้นโดยอัตโนมัติเมื่อมีการเปลี่ยนแปลงดังนั้นคุณไม่ต้องกังวลเกี่ยวกับสิ่งใด อย่างไรก็ตามROWVERSIONประเภทคือ 8 ไบต์ซึ่งสามารถเพิ่มได้เมื่อจัดการกับตารางและ / หรือหลายแถว

    มีข้อดีข้อเสียของวิธีการสองข้อต่อไปนี้ในการจัดการกับการตรวจจับสถานะที่ไม่สอดคล้องกันที่เกี่ยวข้องกับUPDATEการดำเนินงานดังนั้นคุณจะต้องกำหนดวิธีการที่มี "โปร" มากกว่า "แย้ง" สำหรับระบบของคุณ แต่ในกรณีใดกรณีหนึ่งคุณสามารถหลีกเลี่ยงความล่าช้าระหว่างการสร้างตัวอย่างและการดำเนินการจากสาเหตุที่ทำให้เกิดพฤติกรรมนอกความคาดหวังของผู้ใช้

  • หากคุณกำลังทำโหมด "ดูตัวอย่าง" ผู้ใช้ปลายทางนอกเหนือจากการจับภาพสถานะของระเบียนในเวลาที่เลือกเวลาผ่านไปและการตรวจสอบที่เวลาการแก้ไขรวมถึงDATETIMEสำหรับSelectTimeและเติมผ่านGETDATE()หรือสิ่งที่คล้ายกัน ส่งผ่านไปยังเลเยอร์แอปเพื่อให้สามารถส่งกลับไปยังโพรซีเดอร์ที่เก็บไว้ (ส่วนใหญ่เป็นพารามิเตอร์อินพุตเดียว) เพื่อให้สามารถตรวจสอบได้ในขั้นตอนการจัดเก็บ จากนั้นคุณสามารถตรวจสอบว่าถ้าดำเนินการไม่ได้เป็นโหมด "Preview" แล้ว@SelectTimeความต้องการค่าจะไม่เกินนาที X GETDATE()ก่อนที่จะมีมูลค่าปัจจุบันของ อาจจะ 2 นาที 5 นาที? มีโอกาสมากที่สุดไม่เกิน 10 นาที โยนข้อผิดพลาดหากDATEDIFFใน MINUTES มีค่าเกินขีด จำกัด นั้น


4

วิธีที่ง่ายที่สุดมักจะดีที่สุดและฉันก็ไม่ได้มีปัญหาเรื่องการทำสำเนาโค้ดใน SQL มากนักโดยเฉพาะอย่างยิ่งไม่ใช่ในโมดูลเดียวกัน หลังจากแบบสอบถามทั้งสองกำลังทำสิ่งที่แตกต่างกัน ดังนั้นทำไมไม่ใช้ 'เส้นทางที่ 1' หรือทำให้มันง่ายและเพียงแค่มีสองส่วนใน proc ที่เก็บไว้หนึ่งรายการเพื่อจำลองงานที่คุณต้องทำและสิ่งที่ต้องทำเช่นสิ่งนี้:

CREATE TABLE dbo.user_table ( rowId INT IDENTITY PRIMARY KEY, a INT NOT NULL, someGuid UNIQUEIDENTIFIER DEFAULT NEWID() );
GO
CREATE PROCEDURE [dbo].[PREVIEW_EXAMPLE2]

    @preview CHAR(1) = 'Y'

AS

    SET NOCOUNT ON

    --!!TODO add error handling

    IF @preview = 'Y'

        -- Simulate INSERT; could be more complex
        SELECT 
            ISNULL( ( SELECT MAX(rowId) FROM dbo.user_table ), 0 ) + 1 AS rowId,
            42 AS a,
            NEWID() AS someGuid

    ELSE

        -- Actually do the INSERT, return inserted values
        INSERT INTO dbo.user_table ( a )
        OUTPUT inserted.rowId, inserted.a, inserted.someGuid
        VALUES ( 42 )

    RETURN

GO

สิ่งนี้มีความได้เปรียบในการจัดทำเอกสารด้วยตนเอง (เช่นIF ... ELSEง่ายต่อการติดตาม) ความซับซ้อนต่ำ (เทียบกับจุดบันทึกด้วยวิธีการตัวแปรตาราง IMO) จึงมีโอกาสน้อยที่จะมีข้อบกพร่อง (จุดที่ยอดเยี่ยมจาก @Cody)

เกี่ยวกับประเด็นของคุณเกี่ยวกับความมั่นใจต่ำฉันไม่แน่ใจว่าฉันเข้าใจ ตรรกะสองแบบสอบถามที่มีเกณฑ์เดียวกันควรทำสิ่งเดียวกัน มีความเป็นไปได้ที่จะเกิดความไม่ตรงกันระหว่าง cardinality UPDATEและ a SELECTแต่จะเป็นคุณลักษณะของการรวมและเกณฑ์ของคุณ คุณอธิบายเพิ่มเติมได้ไหม

คุณควรตั้งค่าNULL/ NOT NULLคุณสมบัติและตัวแปรตารางและตารางของคุณพิจารณาการตั้งค่าคีย์หลัก

วิธีการเดิมของคุณดูเหมือนว่าบิตที่ซับซ้อนมากกว่าอาจจะมีแนวโน้มที่จะตายในขณะที่INSERT/ UPDATE/ การดำเนินงานจำเป็นต้องมีระดับที่สูงขึ้นกว่าล็อคธรรมดาDELETESELECTs

ฉันสงสัยว่าโลกแห่งความเป็นจริงของคุณมีความซับซ้อนมากขึ้นดังนั้นหากคุณรู้สึกว่าวิธีการข้างต้นไม่ได้ผลสำหรับพวกเขาให้โพสต์กลับด้วยตัวอย่างเพิ่มเติม


3

ความกังวลของฉันมีดังนี้

  • การจัดการธุรกรรมไม่เป็นไปตามรูปแบบมาตรฐานของการซ้อนในบล็อกเริ่มต้นลอง / เริ่มจับ หากนี่คือเทมเพลตจากนั้นในขั้นตอนการจัดเก็บที่มีอีกไม่กี่ขั้นตอนคุณสามารถออกจากการทำธุรกรรมนี้ในโหมดตัวอย่างด้วยข้อมูลที่ยังคงแก้ไข

  • การทำตามรูปแบบจะเพิ่มงานของนักพัฒนา หากพวกเขาเปลี่ยนคอลัมน์ภายในพวกเขาก็ต้องแก้ไขคำนิยามตัวแปรตารางจากนั้นแก้ไขคำนิยามตาราง temp จากนั้นแก้ไขคอลัมน์แทรกที่ท้าย มันจะไม่เป็นที่นิยม

  • บางโพรซีเดอร์ที่เก็บไว้จะไม่ส่งคืนรูปแบบข้อมูลเดียวกันทุกครั้ง คิดว่า sp_WhoIsActive เป็นตัวอย่างทั่วไป

ฉันไม่ได้ให้วิธีที่ดีกว่าในการทำ แต่ฉันไม่คิดว่าสิ่งที่คุณมีคือรูปแบบที่ดี

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.