Database
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Database

Giám sát các bản sao lưu trong các phiên bản

Giới thiệu

Trong hai hoặc ba tháng qua, tôi đã được hỏi hai lần về một giải pháp dành cho SQL Server để hợp nhất một báo cáo sao lưu cho một số phiên bản SQL Server trong một doanh nghiệp. Câu hỏi này đến từ những người bạn không nhất thiết muốn bỏ tiền ra mua một công cụ nhưng thiên về tận dụng các khả năng của SQL Server. Tôi đã nghĩ về hai cách khả thi để đạt được điều này:

  1. Sử dụng Máy chủ được Liên kết, chế độ xem danh mục, Công việc Tác nhân SQL và Thư cơ sở dữ liệu
  2. Sử dụng Máy chủ Quản lý Trung tâm

Trong bài viết này, tôi sẽ trình bày phần đầu tiên và hy vọng chúng ta sẽ có phần thứ hai của bài viết sau này.

Tình huống

Môi trường của tôi bao gồm một bộ ba phiên bản nằm trên các máy chủ riêng biệt trên AWS. Các "máy chủ" này thực sự là Amazon EC2 chạy SQL Server 2017 RTM CU5. Chúng tôi cũng sẽ tận dụng Dịch vụ Email Đơn giản của Amazon để định cấu hình Thư cơ sở dữ liệu. Trong quá trình sản xuất, bạn chắc chắn có thể sử dụng Máy chủ email tại chỗ của mình và đạt được các mục tiêu tương tự. Bạn sẽ nhận thấy ở phần sau của bài viết này rằng tên máy chủ (và do đó là tên phiên bản) là giống nhau. Điều này là do các máy chủ đã được sao chép từ cùng một Hình ảnh Máy Amazon (xin thứ lỗi cho "sự lười biếng"). Điều này có thể sẽ không xảy ra trong quá trình sản xuất.

Thực hiện một vài bản sao lưu

Hãy bắt đầu bằng cách sao lưu một số cơ sở dữ liệu trên ba trường hợp này. Điều này sẽ tạo ra dữ liệu mà chúng tôi sẽ làm việc với. Sau đó, chúng tôi sẽ xác minh các bản sao lưu được ghi lại trong bảng hệ thống msdb.dbo.backupset msdb.dbo.backupmediafamily . Bạn có thể xem lại mô tả đầy đủ của các bảng này trên Tài liệu Microsoft này hoặc chỉ cần sử dụng sp_columns .

 - Liệt kê 1:Sao lưu trên các phiên bản - Sao lưu một DB duy nhất với một cơ sở dữ liệu sọc sao lưu newdb vào disk ='newdb.bak' - Sao lưu tất cả các DB trong phiên bản với dấu thời gian trong bộ sao lưu nameexec sp_MSforeachdb @ command1 ='khai báo @path varchar (300) set @path =' 'M:\ MSSQL \ BACKUP \? _ Backup' '+ convert (varchar (10), getdate (), 110) +' '.bak''print @pathbackup cơ sở dữ liệu [?] tới [email protected]'-- Sao lưu một DB lớn duy nhất với bốn cơ sở dữ liệu dự phòng sọc [PieceMealDB] todisk ='M:\ MSSQL \ BACKUP \ PieceMealDB_01.bak', disk ='M:\ MSSQL \ BACKUP \ PieceMealDB_02 .bak ', disk =' M:\ MSSQL \ BACKUP \ PieceMealDB_03.bak ', disk =' M:\ MSSQL \ BACKUP \ PieceMealDB_04.bak'withstats =10 

Hình 3. Mô tả msdb.dbo.backupset

Kiểm tra bản sao lưu

Tập lệnh sau tận dụng lợi thế của hai bản sao lưu chế độ xem danh mục và backupmediafamily để kiểm tra lịch sử của các bản sao lưu được tạo trên một phiên bản của SQL Server. Danh mục bộ sao lưu chứa một hàng cho mỗi bộ sao lưu. Tập hợp sao lưu được định nghĩa là nội dung của thao tác sao lưu được thêm vào tập phương tiện. Tập phương tiện là một tập hợp thứ tự phương tiện mà một hoặc nhiều hoạt động sao lưu đã ghi vào đó.

 - Liệt kê 2:Kiểm tra bản sao lưu bằng bảng msdb --PRINT 'Kiểm tra cơ sở dữ liệu đã sao lưu thành công' sử dụng msdbgoselect bus.database_name, bus.type, case bus.type khi 'D' rồi 'Đầy' khi 'I' rồi 'Khác biệt' khi 'L' rồi đến 'Nhật ký' end backup_type, bus.backup_start_date, bus.backup_finish_date, (((DATEPART (HH, bus.backup_finish_date)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + (((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date)) ) [backup_time (secs)], bus.backup_size, bmf.physical_device_name from backupet busjoin backupmediafamily bmf on bus.media_set_id =bmf.media_set_idwhere bus.backup_start_date> =(getdate () - 7) order by buspre>backup desc  

Hình 5. Đầu ra mẫu của séc dự phòng

Kiểm tra bản sao lưu trên các trường hợp khác

Sử dụng Máy chủ được Liên kết, chúng tôi có thể trích xuất dữ liệu từ các phiên bản từ xa. Trong trường hợp này, chúng tôi sẽ sử dụng một máy chủ được liên kết đơn giản để trích xuất thông tin lịch sử sao lưu từ cơ sở dữ liệu msdb của hai phiên bản từ xa. Cấu hình bảo mật cho các Máy chủ được Liên kết này hoàn toàn phụ thuộc vào bạn nhưng chúng tôi đã giữ ở đây rất đơn giản vì mục tiêu của chúng tôi. Liệt kê 3 cho thấy tập lệnh có thể sử dụng các máy chủ được Liên kết này để tổng hợp dữ liệu lịch sử sao lưu.

Hình 6. Một máy chủ được liên kết đơn giản

Hình 7. Máy chủ được liên kết cho hai phiên bản từ xa

 - Liệt kê 3:Kiểm tra Bản sao lưu bằng cách sử dụng bảng msdb trên Máy chủ được Liên kết Sử dụng msdbgowith srva as (select bus.server_name instance, bus.database_name, bus.type, case bus.type khi 'D' rồi 'Full' khi 'I' sau đó là 'Differential' khi 'L' rồi đến 'Log' end backup_type, bus.backup_start_date, bus.backup_finish_date, (((DATEPART (HH, bus.backup_finish_date)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + (((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date) )) [backup_time (secs)], bus.backup_size, bmf.physical_device_name from backupet busjoin backupmediafamily bmf on bus.media_set_id =bmf.media_set_idwhere bus.backup_start_date> =(getdate () - 3)), srvb as (select bus.server_ select instance, bus.database_name, bus.type, case bus.type khi 'D' thì 'Full' khi 'I' rồi 'Differential' khi 'L' thì 'Log' end backup_type, bus.backup_start_date, bus.backup_finish_date, ( ((DATEPART (HH, bus.backup_finish_d ate)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + ((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + ((( DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date))) [backup_time (giây)], bus.backup_size, bmf.physical_device_name from [10.0.1.155] .msdb.dbo.backupset busjoin [10.0. 1.155] .msdb.dbo.backupmediafamily bmf trên bus.media_set_id =bmf.media_set_idwhere bus.backup_start_date> =(getdate () - 3)), srvc as (select bus.server_name instance, bus.database_name, bus.type, case bus .type khi 'D' rồi 'Full' khi 'I' rồi 'Differential' khi 'L' rồi đến 'Log' end backup_type, bus.backup_start_date, bus.backup_finish_date, (((DATEPART (HH, bus.backup_finish_date)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + (((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date))) [backup_time (secs)], bus.backup_size, bmf.physical_device_name from [10.0.1.83] .ms db.dbo.backupset busjoin [10.0.1.83] .msdb.dbo.backupmediafamily bmf trên bus.media_set_id =bmf.media_set_idwhere bus.backup_start_date> =(getdate () - 3)) select * from srvaunion select * from srvbunionelect * from srvc; 

Kết hợp SES và Thư cơ sở dữ liệu

Bước tiếp theo chúng tôi thực hiện là tự động kiểm tra này và gửi tập hợp kết quả qua thư cho Quản trị viên cơ sở dữ liệu. Các bước bắt buộc sẽ được tóm tắt như sau:

    1. Định cấu hình Amazon SES . Bạn có thể tìm hiểu cách thiết lập nhanh email trên AWS bằng cách sử dụng tài liệu được cung cấp tại Amazon SES Quick Start. Khi sử dụng dịch vụ email tại chỗ, điều này sẽ không cần thiết đối với DBA.
    2. Định cấu hình Thư cơ sở dữ liệu . Bài viết này không nhằm mục đích trình diễn Thư cơ sở dữ liệu vì vậy chúng tôi chỉ cung cấp ảnh chụp màn hình của cấu hình tài khoản thư SQL:

      Hình 7. Cài đặt tài khoản thư SQL

      • Số cổng khi sử dụng SES để gửi email là 587 KHÔNG PHẢI 25
      • Amazon SES yêu cầu kết nối an toàn, do đó, hộp kiểm được xác định bằng lilac (Hình 7) phải được chọn
      • Xác thực cơ bản bằng thông tin đăng nhập SMTP là bắt buộc (tức là không cho phép xác thực ẩn danh).

      Chúng ta chỉ cần lưu ý một số điều khi sử dụng Amazon SES cho Database Mail:

    3. Định cấu hình SQL Agent để sử dụng Cấu hình Thư . SQL Server Agent phải được định cấu hình để sử dụng hồ sơ thư được tạo trong cấu hình Thư cơ sở dữ liệu cho các công việc tác nhân để kích hoạt email. (Xem Hình 8)
    4. Tạo bảng tổ chức . Một bảng phân giai đoạn sẽ chứa tập hợp kết quả tổng hợp cho tất cả dữ liệu lịch sử sao lưu từ các trường hợp chúng tôi đã nhắm mục tiêu bằng Máy chủ được Liên kết. Bảng DDL được hiển thị trong Liệt kê 4.
 - Liệt kê 4:Bảng lịch sử sao lưu DDLSET ANSI_NULLS ONGOSET QUOTED_IDENTIFIER ONGOCREATE TABLE [dbo]. [backuphistory] ([instance] [nvarchar] (128) NULL, [database_name] [nvarchar] (128) NULL, [type] [char] (1) NULL, [backup_type] [varchar] (12) NULL, [backup_start_date] [datetime] NULL, [backup_finish_date] [datetime] NULL, [backup_time (secs)] [int] NULL, [backup_size] [ số] (20, 0) NULL, [physical_device_name] [nvarchar] (260) NULL) BẬT [CHÍNH] ĐI 

Hình 8. Cài đặt tác nhân SQL

Chúng tôi tiếp tục và lập lịch tập lệnh trong danh sách 3 trong Công việc tác nhân SQL và chúng tôi có tập lệnh hoàn chỉnh trong Liệt kê 5.

 - Liệt kê 5:Hoàn thành công việc SQL Agent cho Lịch sử sao lưu Thông báoUSE [msdb] GO / ****** Đối tượng:Công việc [Tóm tắt lịch sử sao lưu Enteprise] Ngày tập lệnh:9/26/2018 10:16:46 CH ****** / BEGIN TRANSACTIONDECLARE @ReturnCode INTSELECT @ReturnCode =0 / ****** Đối tượng:JobCategory [[Chưa được phân loại (Cục bộ)]] Ngày tập lệnh:26/09/2018 10:16:46 CH ** **** / NẾU KHÔNG TỒN TẠI (CHỌN tên TỪ msdb.dbo.syscategories WHERE name =N '[Chưa được phân loại (Cục bộ)]' AND category_class =1) BEGINEXEC @ReturnCode =msdb.dbo.sp_add_category @ class =N'JOB ' , @ type =N'LOCAL ', @ name =N' [Uncategorized (Local)] 'IF (@@ ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollbackENDDECLARE @jobId BINARY (16) EXEC @ReturnCode =msdb. dbo.sp_add_job @ job_name =N'Enteprise Bản tóm tắt lịch sử sao lưu ', @ enable =1, @ allow_level_eventlog =0, @ Inform_level_email =0, @ Inform_level_netsend =0, @ Inform_level_page =0, @ delete_level =0, @ description =N'No mô tả có sẵn. ', @ category_name =N' [Chưa được phân loại (Địa phương)] ', @ owner_login_name =N'TWE NTYTOWERS \ Administrator ', @job_id =@jobId OUTPUTIF (@@ ERROR <> 0 HOẶC @ReturnCode <> 0) GOTO QuitWithRollback / ****** Đối tượng:Bước [Tổng hợp lịch sử sao lưu] Ngày tập lệnh:26/09/2018 10:16:46 PM ****** / EXEC @ReturnCode =msdb.dbo.sp_add_jobstep @ example @ sqldat.com, @ step_name =N'Tổng hợp lịch sử sao lưu ', @ step_id =1, @ cmdexec_success_code =0, @ on_success_action =3, @ on_success_step_id =0, @ on_fail_action =2, @ on_fail_step_id =0, @ retry_attempts =0, @ retry_interval =0, @ os_run_priasty =0, @ subsystem =N'TSQL ', @ command =N' - Kiểm tra Sao lưu sử dụng bảng msdb ---- Trên toàn bộ Máy chủ được Liên kết Sử dụng bảng msdbgotruncate [msdb]. [Dbo]. [Backuphistory]; với srva as (select bus.server_name instance, bus.database_name, bus.type, case bus.type when '' D '' rồi đến '' Đầy đủ '' khi '' I '' rồi '' Khác biệt '' khi '' L '' rồi đến '' Nhật ký '' end backup_type, bus.backup_start_date, bus.backup_finish_date, (((DATEPART (HH , bus.backup_finish_date)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_fin) ish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + ((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date)) [backup_time (secs)], bus .backup_size, bmf.physical_device_name từ backupet busjoin backupmediafamily bmf trên bus.media_set_id =bmf.media_set_idwhere bus.backup_start_date> =(getdate () - 3)), srvb as (select bus.server_name, instance, bus.dattyabase_name, bus.dattyabase_name, instance, bus.dattyabase_name case bus.type khi '' D '' rồi đến '' Full '' khi '' I '' rồi '' Differential '' khi '' L '' rồi đến '' Log '' end backup_type, bus.backup_start_date, bus.backup_finish_date , (((DATEPART (HH, bus.backup_finish_date)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date) ))) * 60) + (((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date))) [backup_time (secs)], bus.backup_size, bmf.physical_device_name from [10.0.1.155] .msdb.dbo.backupset busjoin [10.0.1.155] .msdb.dbo.backupmediafamily bmf trên bus.media_set_id =bmf.media_set_idwhere b us.backup_start_date> =(getdate () - 3)), srvc as (select bus.server_name instance, bus.database_name, bus.type, case bus.type when '' D '' then '' Full '' when '' I '' then '' Differential '' khi '' L '' thì '' Nhật ký '' end backup_type, bus.backup_start_date, bus.backup_finish_date, (((DATEPART (HH, bus.backup_finish_date)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + (((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date))) [backup_time (giây)], bus.backup_size, bmf.physical_device_name from [10.0.1.83] .msdb.dbo.backupset busjoin [10.0.1.83] .msdb.dbo.backupmediafamily bmf trên bus.media_set_id =bmf.media_set_idwhere bus.backup_start_date> =(getdate () - 3)) chèn vào [msdb]. [dbo]. [backuphistory] select * from srvaunion select * from srvbunionelect * from srvc; ', @database_name =N'msdb ', @ flags =0IF (@@ LỖI <> 0 HOẶC @ReturnCode <> 0) GOTO QuitWithRollback / ****** Đối tượng:Bước [Truy vấn Máy chủ Thành viên để sao lưu] Ngày tập lệnh:26/09/2018 10:16:46 CH ****** / EXEC @ReturnCode =msdb.dbo.sp_add_jobstep @ example @ sqldat.com, @ step_name =N'Query Máy chủ thành viên để sao lưu ', @ step_id =2, @ cmdexec_success_code =0, @ on_success_action =3, @ on_success_step_id =0, @ on_fail_action =2, @ on_fail_step_id =0, @ retry_attempts =0, @ retry_interval =0, @ subsystem =0, @ subsystem =0, @ subsystem =0, @ subsystem =0, @ subsystem =0 N'TSQL ', @ command =N'DECLARE @tableHTML NVARCHAR (MAX); SET @tableHTML =N' '

Tóm tắt lịch sử sao lưu doanh nghiệp

' '+ N' '' '+ N' ' '' + N '' '' + N '' '' + N '' '' + N '' '' + N '' '' + N '' '' + CAST ((SELECT td =bus.instance, '' '', td =bus.database_name, '' '' , td =bus.backup_start_date, '' '', td =bus.backup_finish_date, '' '', td =(((DATEPART (HH, bus.backup_finish_date)) - (DATEPART (HH, bus.backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + (((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus. backup_start_date))), '' '', td =bus.backup_size, '' '', td =bus.physical_device_name FROM backuphistory as bus WHERE bus.backup_start_date> =(getdate () - 7) ĐẶT HÀNG BẰNG bus.backup_start_date desc FOR XML PATH ('' tr ''), TYPE) AS NVARCHAR (MAX)) + N ''
Tên phiên bản Tên cơ sở dữ liệu Ngày bắt đầu sao lưu Ngày kết thúc sao lưu Thời gian sao lưu (giây) Kích thước sao lưu Tên thiết bị vật lý
'' + ''

 

Trân trọng cảm ơn,

 

Hoạt động Cơ sở dữ liệu Doanh nghiệp

 

''; EXEC msdb.dbo.sp_send_dbmail @ người nhận ='' [email protected]; [email protected] '', @subject ='' Tóm tắt lịch sử sao lưu doanh nghiệp '', @body =@tableHTML, @body_format ='' HTML ''; ', @ database_name =N'msdb ', @ flags =0IF (@@ LỖI <> 0 HOẶC @ReturnCode <> 0) GOTO QuitWithRollback / ****** Đối tượng:Bước [Thư Hoàn thành Kết quả Đặt thành Hỗ trợ] Ngày tập lệnh:9/26 / 2018 10:16:46 PM ****** / EXEC @ReturnCode =msdb.dbo.sp_add_jobstep @ example @ sqldat.com, @ step_name =N'Mail Hoàn thành kết quả được đặt thành hỗ trợ ', @ step_id =3, @cmdexec_success_code =0, @ on_success_action =1, @ on_success_step_id =0, @ on_fail_action =2, @ on_fail_step_id =0, @ retry_attempts =0, @ retry_interval =0, @ os_run_priasty =0, @ subsystem =N'TSQL ', @ command =N 'DECLARE @tableHTML NVARCHAR (MAX); SET @tableHTML =N' '

Tóm tắt lịch sử sao lưu doanh nghiệp

' '+ N' ' '' + N '' '' + N '' '' + N '' '' + N '' '' + N '' '' + N '' '' + N ' '' '+ CAST ((SELECT td =bus.instance,' '' ', td =bus. database_name, '' '', td =bus.backup_start_date, '' '', td =bus.backup_finish_date, '' '', td =(((DATEPART (HH, bus.backup_finish_date)) - (DATEPART (HH, bus .backup_start_date))) * 3600) + (((DATEPART (MI, bus.backup_finish_date)) - (DATEPART (MI, bus.backup_start_date))) * 60) + (((DATEPART (SS, bus.backup_finish_date)) - DATEPART (SS, bus.backup_start_date))), '' '', td =bus.backup_size, '' '', td =bus.physical_device_name FROM backuphistory as bus WHERE bus.backup_start_date> =(getdate () - 7) ORDER BY bus.backup_start_date desc FOR XML PATH ('' tr ''), TYPE ) NHƯ NVARCHAR (MAX)) + N ''
Tên trường hợp Tên cơ sở dữ liệu Ngày bắt đầu sao lưu Ngày kết thúc sao lưu Thời gian sao lưu (giây) Kích thước sao lưu Tên thiết bị vật lý
'' + ''

 

Trân trọng cảm ơn,

 

Hoạt động Cơ sở dữ liệu Doanh nghiệp

 

''; EXEC msdb.dbo.sp_send_dbmail @ người nhận ='' [email protected]; [email protected] '', @subject ='' Tóm tắt lịch sử sao lưu doanh nghiệp '', @body =@tableHTML, @body_format ='' HTML ''; ', @ database_name =N'msdb ', @ flags =0IF (@@ ERROR <> 0 HOẶC @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode =msdb.dbo.sp_update_job @job_id =@jobId, @start_step_id =1IF (@@ ERROR <> 0 HOẶC @ReturnCode <> 0) GOTO QuitWithRollbackEXEC @ReturnCode =msdb.dbo.sp_add_jobserver @job_id =@jobId, @server_name =N '(local)' IF (@@ ERROR <> 0 HOẶC @ReturnCode <> 0) GOTo EndSaveQuitWithRollback:IF (@@ TRANCOUNT> 0) GIAO DỊCH ROLLBACKEndSave:ĐI

Thực hiện công việc này dẫn đến kết quả được hiển thị trong Hình 9. Bảng được tạo bằng HTML rất đơn giản và có thể được phát triển thêm để phù hợp với nhu cầu của bạn.

Hình 9. Đầu ra email của thực thi công việc tác nhân SQL

Kết luận

Chúng tôi đã trải qua một phương pháp đơn giản để tổng hợp thông tin lịch sử sao lưu (và có thể là bất kỳ dữ liệu nào khác có trong cơ sở dữ liệu hệ thống) bằng cách sử dụng các máy chủ được liên kết. Chúng tôi tiếp tục tự động hóa quá trình này bằng cách sử dụng SQL Agent, Database Mail và một chút HTML. Phương pháp này có vẻ hơi thô và tôi chắc chắn rằng có những công cụ có thể làm tốt hơn nhiều, nhưng đây sẽ là mục đích máy chủ cho những người mới bắt đầu với SQL Server hoặc các môi trường có ngân sách thấp. Với một chút sáng tạo, bạn có thể tùy chỉnh thêm các tập lệnh và điều chỉnh các tập lệnh cho các mục đích sử dụng khác.

Tài liệu tham khảo

  1. Định cấu hình Thư cơ sở dữ liệu
  2. Bắt đầu với Amazon SES
  3. Máy chủ được Liên kết
  4. Lịch sử Sao lưu và Thông tin Tiêu đề

  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Giảm thiểu tác động của việc mở rộng cột IDENTITY - phần 4

  2. Chỉ mục đã lọc và Cột BAO GỒM

  3. DELETE VS DROP trong SQL

  4. Làm thế nào để loại bỏ một ràng buộc duy nhất trong SQL?

  5. Câu lệnh SQL SELECT