2011-08-22 20 views
44

Tôi đang sử dụng dự án cơ sở dữ liệu SQL 2008 (trong phòng thu trực quan) để quản lý lược đồ và dữ liệu thử nghiệm ban đầu cho dự án của tôi. Dự án atabase sử dụng triển khai bài đăng bao gồm một số tập lệnh khác sử dụng cú pháp ": r" của SQLCMD.Logic điều kiện trong kịch bản lệnh PostDeployment.sql sử dụng SQLCMD

Tôi muốn có thể có điều kiện bao gồm các tệp nhất định dựa trên biến SQLCMD. Điều này sẽ cho phép tôi chạy dự án nhiều lần với bản dựng hàng đêm của chúng tôi để thiết lập các phiên bản khác nhau của cơ sở dữ liệu với các cấu hình khác nhau của dữ liệu (cho một hệ thống nhiều người thuê).

Tôi đã thử những điều sau đây:

IF ('$(ConfigSetting)' = 'Configuration1') 
    BEGIN 
    print 'inserting specific configuration' 
:r .\Configuration1\Data.sql 
    END 
ELSE 
    BEGIN 
    print 'inserting generic data' 
:r .\GenericConfiguration\Data.sql 
    END 

Nhưng tôi nhận được một lỗi biên dịch: SQL01260: Một lỗi phân tích cú pháp gây tử vong đã xảy ra: Script.PostDeployment.sql

Có ai nhìn thấy lỗi này hay quản lý để cấu hình kịch bản postdeployment của họ để được linh hoạt theo cách này? Hoặc tôi đang đi về điều này một cách sai lầm hoàn toàn?

Cảm ơn, Rob

T.B. Tôi cũng đã thử thay đổi điều này xung quanh để đường dẫn đến tệp là một biến, similar to this post. Nhưng điều này mang lại cho tôi một lỗi nói rằng đường dẫn không chính xác.

Trả lời

31

CẬP NHẬT

bây giờ tôi đã phát hiện ra rằng if/else cú pháp trên không hiệu quả đối với tôi bởi vì một số kịch bản liên kết của tôi đòi hỏi một tuyên bố GO. Về cơ bản: r chỉ nhập nội tuyến tập lệnh, vì vậy điều này trở thành sytax không hợp lệ.

Nếu bạn cần câu lệnh GO trong tập lệnh được liên kết (như tôi làm) thì không có cách nào dễ dàng, tôi đã tạo một số kịch bản triển khai bài đăng và sau đó thay đổi dự án của tôi để ghi đè kịch bản đăng bài chính tại thời gian xây dựng tùy thuộc vào cấu hình xây dựng. Điều này hiện đang làm những gì tôi cần, nhưng có vẻ như phải có một cách dễ dàng hơn!

Đối với bất kỳ ai cần điều tương tự - I found this post useful

Vì vậy, trong dự án của tôi, tôi có bài triển khai các file sau:

  • Script.PostDeployment.sql (trống tập tin mà sẽ được thay thế)
  • Default.Script.PostDeployment.sql (liên kết đến tập lệnh cần thiết cho cấu hình dữ liệu chuẩn)
  • Configuration1.Script.PostDeployment.sql (liên kết đến tập lệnh cần thiết cho cấu hình dữ liệu cụ thể)

sau đó tôi thêm vào phần sau đây để kết thúc hồ sơ dự án (click chuột phải dỡ bỏ và sau đó click chuột phải chỉnh sửa):

<Target Name="BeforeBuild"> 
     <Message Text="Copy files task running for configuration: $(Configuration)" Importance="high" /> 
     <Copy Condition=" '$(Configuration)' == 'Release' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" /> 
     <Copy Condition=" '$(Configuration)' == 'Debug' " SourceFiles="Scripts\Post-Deployment\Default.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" /> 
     <Copy Condition=" '$(Configuration)' == 'Configuration1' " SourceFiles="Scripts\Post-Deployment\Configuration1.Script.PostDeployment.sql" DestinationFiles="Scripts\Post-Deployment\Script.PostDeployment.sql" OverwriteReadOnlyFiles="true" /> 
    </Target> 

Cuối cùng, bạn sẽ cần phải thiết lập phù hợp với xây dựng cấu hình trong dung dịch.

Ngoài ra, cho bất cứ ai cố gắng quanh công việc khác, tôi cũng đã cố gắng sau mà không cần bất kỳ may mắn:

  1. Tạo sự kiện bài build để sao chép các tập tin thay vì phải hack hồ sơ dự án XML. tôi không thể làm điều này để làm việc vì tôi không thể tạo đường dẫn chính xác cho tệp kịch bản triển khai bài đăng. This connect issue describes the problem

  2. Sử dụng các biến cho đường dẫn tập lệnh để chuyển cho lệnh: r. Nhưng tôi đã gặp một số lỗi với cách tiếp cận này.

+0

Với yêu cầu tuyên bố GO, tôi đã làm việc xung quanh này trước bằng cách thực hiện báo cáo kết quả như SQL động. Đó không phải là một dự án MS Database. YMMV. – fiat

13

Dưới đây là cách tôi xử lý triển khai có điều kiện trong quy trình triển khai bài đăng để triển khai dữ liệu thử nghiệm cho cấu hình Gỡ lỗi nhưng không phát hành.

Đầu tiên, trong trình thám hiểm giải pháp, mở thư mục thuộc tính dự án và bấm chuột phải để thêm tệp SqlCmd.variables mới.

Đặt tên tệp là Debug.sqlcmdvars.

Trong tệp, thêm biến tùy chỉnh của bạn và sau đó thêm biến cuối cùng được gọi là $(BuildConfiguration) và đặt giá trị thành Gỡ lỗi.

Lặp lại quy trình để tạo Release.sqlcmdvars, đặt $(BuildConfiguration) để phát hành.

Bây giờ, định cấu hình cấu hình của bạn: Mở trang thuộc tính dự án cho tab Triển khai. Trên menu thả xuống trên cùng, đặt cấu hình là Gỡ lỗi. Trên trình đơn thả xuống dưới cùng, (Sql command variables), đặt tệp thành Properties \ Debug.sqlcmdvars.

Lặp lại để phát hành dưới dạng: Trên menu thả xuống trên cùng, hãy đặt cấu hình sẽ là Bản phát hành. Trên trình đơn thả xuống dưới cùng, (Sql biến lệnh), đặt tệp thành Thuộc tính \ Release.sqlcmdvars.

Bây giờ, trong tập tin Script.PostDeployment.sql của bạn, bạn có thể chỉ định logic có điều kiện như:

IF 'Debug' = '$(BuildConfiguration)' 
BEGIN 
PRINT '***** Creating Test Data for Debug configuration *****'; 
:r .\TestData\TestData.sql 
END 

Trong giải pháp Explorer, bấm chuột phải vào các giải pháp cấp cao nhất và mở Configuration Manager. Bạn có thể chỉ định cấu hình nào đang hoạt động cho bản dựng của mình. Bạn cũng có thể chỉ định cấu hình trên dòng lệnh MSBUILD.EXE.

Hiện tại, các nhà phát triển của bạn có dữ liệu thử nghiệm chứ không phải bản phát hành bản phát hành của bạn!

+9

Năm 2015 và tôi có SSDT mới nhất và U201 VS2013 và không có tab nào được gọi là "Triển khai" cũng như tôi thậm chí không thấy bất kỳ cách nào để nhập một tệp biến SQLCMD. Thực sự bối rối .. – riix

8

Khi Rob làm việc, câu lệnh GO không được phép trong các tập lệnh SQL được liên kết vì điều này sẽ lồng trong câu lệnh BEGIN/END.

Tuy nhiên, tôi có một giải pháp khác nhau để mình - nếu có thể, loại bỏ bất kỳ GO báo cáo từ các kịch bản tham chiếu, và đặt một trong những đơn sau khi tuyên bố END:

IF '$(DeployTestData)' = 'True' 
BEGIN 
    :r .\TestData\Data.sql 
END 
GO -- moved from Data.sql 

Lưu ý rằng tôi cũng đã tạo một biến mới trong tệp sqlcmdvars của tôi có tên $ (DeployTestData) cho phép tôi bật/tắt triển khai tập lệnh thử nghiệm.

+1

Tôi đã đi xuống con đường này là tốt, tuy nhiên nó áp đặt một yêu cầu tiềm ẩn rằng tất cả các kịch bản có các biến được đặt tên duy nhất. Điều này có thể là một vấn đề với cơ sở dữ liệu phức tạp. – bwerks

+0

Tôi đã đi xuống con đường này và nó hoạt động tốt. Cảm ơn! – Raffaeu

12

Tôi đã cố gắng giải quyết vấn đề bằng cách sử dụng noexec method.

Vì vậy, thay vì điều này:

IF ('$(ConfigSetting)' = 'Configuration1') 
BEGIN 
    print 'inserting specific configuration' 
    :r .\Configuration1\Data.sql 
END 

tôi đảo ngược các điều kiện và thiết lập noexec ON để bỏ qua báo cáo kết quả nhập khẩu (s) thusly:

IF ('$(ConfigSetting)' <> 'Configuration1') 
    SET NOEXEC ON 

:r .\Configuration1\Data.sql 

SET NOEXEC OFF 

Hãy chắc chắn rằng bạn bật nó lùi lại nếu bạn muốn thực thi bất kỳ câu lệnh nào sau đó.

+0

Làm việc cho tôi. Ý tưởng tuyệt vời. Vẫn hoạt động trong SSDT cho VS 2013 trong các kịch bản PostDeploy. – bwerks

1

Tôi tìm thấy một hack from an MSDN blog hoạt động khá tốt. Bí quyết là viết các lệnh vào một tệp kịch bản tạm thời và sau đó thực thi tập lệnh đó thay thế. Về cơ bản tương đương với SQL động cho SQLCMD.

-- Helper newline variable 
:setvar CRLF "CHAR(13) + CHAR(10)" 
GO 
-- Redirect output to the TempScript.sql file 
:OUT $(TEMP)\TempScript.sql 

IF ('$(ConfigSetting)' = 'Configuration1') 
    BEGIN 
    PRINT 'print ''inserting specific configuration'';' + $(CRLF) 
    PRINT ':r .\Configuration1\Data.sql' + $(CRLF) 
    END 
ELSE 
    BEGIN 
    PRINT 'print ''inserting generic data'';' + $(CRLF) 
    PRINT ':r .\GenericConfiguration\Data.sql' + $(CRLF) 
    END 
GO 
-- Change output to stdout 
:OUT stdout 

-- Now execute the generated script 
:r $(TEMP)\TempScript.sql 
GO 

File TempScript.sql sau đó sẽ chứa một trong hai:

print 'inserting specific configuration'; 
:r .\Configuration1\Data.sql 

hoặc

print 'inserting generic data'; 
:r .\GenericConfiguration\Data.sql 

tùy thuộc vào giá trị của $(ConfigSetting) và sẽ không có vấn đề với GO báo cáo vv khi nó là Thực thi.

+0

Thật đáng tiếc là nó không hoạt động. Nếu trước/sau triển khai các kịch bản được hỗ trợ: nó sẽ rất tuyệt, nhưng bạn sẽ gặp lỗi "không được hỗ trợ" nếu bạn thử. – bielawski

1

Tôi lấy cảm hứng từ giải pháp của Rob Bird. Tuy nhiên, tôi chỉ đơn giản là sử dụng các sự kiện xây dựng để thay thế các kịch bản triển khai bài dựa trên cấu hình xây dựng đã chọn.

  1. Tôi có một tập lệnh triển khai bài đăng "giả" trống.
  2. Tôi thiết lập sự kiện dựng sẵn để thay thế tệp "giả" này dựa trên cấu hình xây dựng đã chọn (xem ảnh đính kèm).
  3. Tôi thiết lập sự kiện sau khi xây dựng để đặt tệp "giả" trở lại sau khi quá trình xây dựng hoàn tất (xem ảnh đính kèm). Lý do là tôi không muốn tạo thay đổi trong điều khiển thay đổi sau khi xây dựng.

Build Events setup example

Các vấn đề liên quan