กําหนดค่าการควบคุมแหล่งที่มาและจัดการข้อมูลอ้างอิง

เสร็จสมบูรณ์เมื่อ

โครงการฐานข้อมูล SQL ที่ไม่มีการควบคุมแหล่งที่มาเป็นเพียงโฟลเดอร์ของไฟล์บนเครื่องของใครบางคน ทันทีที่แล็ปท็อปของบุคคลนั้นพังหรือนักพัฒนาสองคนแก้ไขกระบวนงานที่เก็บไว้เดียวกันคุณจะกลับไปที่จุดเริ่มต้น การวางโครงการใน Git จะช่วยให้คุณมีประวัติการเปลี่ยนแปลง การทํางานร่วมกันผ่านการแตกแขนงและคําขอดึงข้อมูล และรากฐานที่ไปป์ไลน์ CI/CD ทุกรายการต้องการ

แต่การควบคุมแหล่งที่มาเพียงอย่างเดียวไม่สามารถแก้ปัญหาได้ทุกอย่าง ฐานข้อมูลของคุณอาจมีตารางการค้นหา รหัสสถานะ และการกําหนดค่าเริ่มต้นที่อยู่ควบคู่ไปกับ Schema คุณต้องมีกลยุทธ์สําหรับข้อมูลนั้นด้วย

ตั้งค่าตัวควบคุมแหล่งที่มาสําหรับโครงการฐานข้อมูล SQL

เนื่องจากโครงการฐานข้อมูล SQL เป็นเพียง .sql ไฟล์และ .sqlproj ไฟล์ จึงเข้ากับ Git ได้อย่างเป็นธรรมชาติ วัตถุฐานข้อมูลแต่ละรายการจะอยู่ในไฟล์ของตัวเอง ดังนั้น Git จึงติดตามการเปลี่ยนแปลงในระดับวัตถุ การคอมมิตที่ปรับเปลี่ยน Customers ตารางและปรับปรุงกระบวนงานที่เก็บไว้จะแสดงไฟล์ทั้งสองนั้นใน diff ไม่ใช่สคริปต์การโยกย้ายแบบเสาหินที่มีการเปลี่ยนแปลงที่ไม่เกี่ยวข้องหลายสิบรายการ

ในการเริ่มต้นใช้งาน ให้เริ่มต้นที่เก็บ Git ในโฟลเดอร์โครงการ:

cd MyDatabaseProject
git init
git add .
git commit -m "Initial commit of database project"

จัดระเบียบโฟลเดอร์โครงการ

โครงสร้างโฟลเดอร์ที่สอดคล้องกันทําให้โครงการสามารถนําทางได้อย่างรวดเร็ว รูปแบบที่พบบ่อยที่สุดจัดกลุ่มไฟล์ตามชนิดออบเจ็กต์:

MyDatabaseProject/
├── MyDatabaseProject.sqlproj
├── Tables/
│   ├── Customers.sql
│   └── Orders.sql
├── Views/
│   └── vw_ActiveCustomers.sql
├── StoredProcedures/
│   └── usp_GetCustomerOrders.sql
├── Scripts/
│   ├── PostDeployment/
│   │   └── seed-data.sql
│   └── PreDeployment/
│       └── prep-db.sql
└── PostDeploy.sql

ด้วยโปรเจ็กต์สไตล์ SDK รูปแบบ globbing เริ่มต้นจะรับทุก .sql ไฟล์ในโฟลเดอร์โดยอัตโนมัติ ไม่จําเป็นต้องป้อนไฟล์ด้วยตนเอง

เพิ่มไฟล์ .gitignore

ให้ที่เก็บมุ่งเน้นไปที่ไฟล์ต้นฉบับโดยไม่รวมเอาต์พุตบิลด์และการตั้งค่าเฉพาะผู้ใช้:

bin/
obj/
*.dacpac
*.user

สร้างขึ้น .dacpac ใหม่จากโปรเจ็กต์ในทุกบิลด์ CI/CD ดังนั้นจึงไม่มีเหตุผลที่จะต้องติดตามใน Git

จัดการข้อมูลอ้างอิงด้วยสคริปต์ก่อนการปรับใช้และหลังการปรับใช้

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

สคริปต์ก่อนการปรับใช้และหลังการปรับใช้ช่วยแก้ปัญหานี้ เป็นสคริปต์ SQL ที่ดําเนินการระหว่างการปรับใช้ แต่อยู่นอกโมเดลฐานข้อมูลที่คอมไพล์แล้ว:

  • สคริปต์ก่อนการปรับใช้จะทํางานก่อนแผนการปรับใช้ ใช้สําหรับงานที่ต้องทําให้เสร็จก่อนการเปลี่ยนแปลง Schema เช่น การทิ้งข้อจํากัดหรือการย้ายข้อมูล
  • สคริปต์หลังการปรับใช้จะทํางานหลังจากแผนการปรับใช้เสร็จสมบูรณ์ ใช้เพื่อเติมข้อมูลอ้างอิง ตารางการค้นหา Seed หรือตั้งค่าเริ่มต้นของแอปพลิเคชัน

เพิ่มสคริปต์ลงในโปรเจ็กต์

โครงการรองรับสคริปต์ก่อนการปรับใช้หนึ่งสคริปต์และสคริปต์หลังการปรับใช้หนึ่งสคริปต์ คุณประกาศรายการ .sqlproj ในไฟล์ที่มี PreDeploy รายการและ PostDeploy รายการ:

<ItemGroup>
    <PreDeploy Include="prep-db.sql" />
</ItemGroup>
<ItemGroup>
    <PostDeploy Include="PostDeploy.sql" />
</ItemGroup>

ใช้ SQLCMD รวมสําหรับไฟล์ข้อมูลหลายไฟล์

ไฟล์สคริปต์หนึ่งไฟล์ไม่ได้หมายถึงไฟล์ขนาดยักษ์ไฟล์เดียว ใช้ไวยากรณ์ SQLCMD :r เพื่อดึงแฟ้มหลายแฟ้มจากจุดเข้าใช้งานเดียว ลักษณะทั่วไป PostDeploy.sql ดังนี้:

:r .\Scripts\PostDeployment\seed-statuses.sql
:r .\Scripts\PostDeployment\seed-regions.sql
:r .\Scripts\PostDeployment\seed-app-settings.sql

ไฟล์ที่อ้างอิงแต่ละไฟล์จะต้องถูกแยกออกจากบิลด์ มิฉะนั้น กระบวนการสร้างจะพยายามคอมไพล์เป็นออบเจ็กต์สคีมาและล้มเหลว ใน .sqlproj ไฟล์ ใช้ Build Remove เพื่อป้องกันการคอมไพล์และทําให้ None Include ไฟล์มองเห็นได้ในโปรเจ็กต์:

<ItemGroup>
    <Build Remove="Scripts\PostDeployment\seed-statuses.sql" />
    <None Include="Scripts\PostDeployment\seed-statuses.sql" />
</ItemGroup>

📝 ทําซ้ํารูปแบบนี้สําหรับแต่ละไฟล์ที่อ้างอิงในสคริปต์ก่อนการปรับใช้หรือหลังการปรับใช้

เขียนสคริปต์ข้อมูลอ้างอิง idempotent

สคริปต์หลังการปรับใช้จะทํางานในทุกการปรับใช้ ไม่ใช่แค่สคริปต์แรก หากคุณใช้คําสั่งธรรมดา INSERT การปรับใช้ครั้งที่สองจะล้มเหลวโดยมีการละเมิดคีย์ที่ซ้ํากัน ใช้ MERGE คําสั่งแทนเพื่อทําให้สคริปต์ปลอดภัยในการเรียกใช้ซ้ํา:

MERGE INTO [dbo].[OrderStatuses] AS target
USING (VALUES
    (1, N'Pending'),
    (2, N'Processing'),
    (3, N'Shipped'),
    (4, N'Delivered'),
    (5, N'Cancelled')
) AS source ([StatusID], [StatusName])
ON target.[StatusID] = source.[StatusID]
WHEN MATCHED THEN
    UPDATE SET [StatusName] = source.[StatusName]
WHEN NOT MATCHED THEN
    INSERT ([StatusID], [StatusName])
    VALUES (source.[StatusID], source.[StatusName]);

เคล็ดลับ

คุณสามารถตรวจสอบความถูกต้องของสคริปต์ก่อนการปรับใช้และหลังการปรับใช้หลังจากสร้างโครงการโดยเปลี่ยน .dacpac นามสกุลไฟล์เป็น .zip และแยกไฟล์ ไฟล์เดียว .sql สําหรับสคริปต์แต่ละชนิดประกอบด้วยเนื้อหา T-SQL ที่รวมกันจากไฟล์ที่อ้างอิงทั้งหมด

ประเด็นสําคัญ

เริ่มต้นที่เก็บ Git ที่ระดับโซลูชัน และใช้.gitignoreไฟล์เพื่อยกเว้นเอาต์พุตบิลด์ เช่น bin/ไฟล์ และobj/.dacpacไฟล์ จัดระเบียบออบเจ็กต์ Schema ลงในโฟลเดอร์ที่สะท้อนโครงสร้างฐานข้อมูล โดยมีหนึ่งไฟล์ต่อออบเจ็กต์ วางข้อมูลอ้างอิงในสคริปต์หลังการปรับใช้ และใช้ SQLCMD :r รวมเพื่อให้แต่ละสคริปต์มุ่งเน้นไปที่ตารางเดียว เมื่อต้องการป้องกันไม่ให้สคริปต์ข้อมูลถูกคอมไพล์เป็นออบเจ็กต์ Schema ให้ใช้ Build Remove และ None Include ใน .sqlproj ไฟล์ เขียน MERGE คําสั่งแทนคําสั่งธรรมดา INSERT เพื่อให้สคริปต์ข้อมูลอ้างอิงมีศักยภาพและปลอดภัยในการเรียกใช้ในทุกการปรับใช้ ถัดไป คุณวางที่เก็บนี้เพื่อทํางานกับเวิร์กโฟลว์การแยกสาขาและคําขอดึงข้อมูล