กําหนดค่าการควบคุมแหล่งที่มาและจัดการข้อมูลอ้างอิง
โครงการฐานข้อมูล 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 เพื่อให้สคริปต์ข้อมูลอ้างอิงมีศักยภาพและปลอดภัยในการเรียกใช้ในทุกการปรับใช้ ถัดไป คุณวางที่เก็บนี้เพื่อทํางานกับเวิร์กโฟลว์การแยกสาขาและคําขอดึงข้อมูล