2009-10-15 35 views
5

Tôi đang làm việc trên bản cập nhật tiếp theo cho StackQL.Tôi có thể đặt giản đồ mặc định cho một thủ tục được lưu trữ không?

Một điều tôi muốn làm là có khả năng truy vấn qua một số bản phát hành. Vì vậy, khi tôi tải dữ liệu tháng 10, ví dụ, tôi đã không xóa cơ sở dữ liệu tháng 9 cũ. Nó vẫn còn ở ngoài kia. Trong thực tế, bạn thậm chí có thể truy vấn nó bằng cách bao gồm tên cơ sở dữ liệu như sau:

select top 10 * from SO_Sept09..Posts 

Điều này sẽ còn quan trọng hơn khi chúng bắt đầu cung cấp dữ liệu cho ServerFault và SuperUser.

Nhưng tôi không thích có toàn bộ cơ sở dữ liệu để hỗ trợ điều này. Tôi muốn đặt tất cả các dữ liệu trong cùng một cơ sở dữ liệu và tách riêng từng bộ riêng biệt thành lược đồ riêng của nó. Nhưng để thực hiện điều này, tôi cần có thể thiết lập lược đồ mặc định như là một phần của thủ tục được lưu trữ chạy truy vấn, dựa trên tham số được truyền cho thủ tục đã lưu trữ, cho biết cơ sở dữ liệu nào người dùng đã chọn từ danh sách thả xuống trong tương lai xuất hiện trên thanh công cụ.

Queries tại StackQL được cuối cùng chỉ truyền cho exec() chức năng như thế này:

exec(@QueryText) 

Có bất cứ điều gì tôi có thể làm một trong hai trong thủ tục lưu trữ hoặc thêm vào trước vào chuỗi QueryText (ala USE [DatabaseName]) để thiết lập mặc định lược đồ được sử dụng trong một truy vấn?

+0

Câu hỏi hay! – RBarryYoung

Trả lời

3

Ngoài sửa đổi @QueryText chính nó, điều duy nhất tôi có thể nghĩ đến là sơ đồ mặc định của người dùng:

ALTER USER SO_Sept09_Reader WITH DEFAULT_SCHEMA = SO_Sept09 

... và sau đó kết nối như một người dùng khác nhau cho mỗi sơ đồ bạn muốn sử dụng. Hack hack. Tuy nhiên, nếu truy vấn của bạn được tạo động (và tôi chắc chắn bạn biết tại sao đó không phải là một ý tưởng tuyệt vời), có thể dễ dàng chỉ thêm một trình giữ chỗ lược đồ vào văn bản truy vấn và chuyển tên lược đồ cùng với với truy vấn đến hàm thay thế.

+0

Thêm trình giữ chỗ lược đồ chắc chắn không phải là một tùy chọn. Trang web cho phép bất cứ ai viết và chạy truy vấn sql một lần nữa kết xuất dữ liệu công khai StackOverflow và họ có thể viết bất kỳ thứ gì. Thay đổi người dùng là ra là tốt, vì điều đó sẽ gây ra vấn đề đồng thời. Nhưng nó cho tôi ý tưởng có thể có nhiều người dùng và chọn chuỗi kết nối khi đang di chuyển. –

+0

Vâng, sau đó là những gì tôi đã đề xuất; một hoặc nhiều người dùng (tĩnh) cho mỗi lược đồ; chuyển đổi người dùng (bằng cách kết nối với chuỗi kết nối phù hợp) khi đang di chuyển. –

1

Một khả năng khác là tạo bản sao của mỗi SP trong mỗi lược đồ, tên bảng chưa sửa đổi trong SP đề cập đến các bảng trong cùng một lược đồ.

Chú giải này không làm việc với SQL động bên trong một SP ví dụ:

CREATE PROCEDURE schema_a.SP 
    @somesql AS varchar(MAX) 
AS 
BEGIN 
    EXEC (@somesql) 
END 

CREATE PROCEDURE schema_b.SP 
    @somesql AS varchar(MAX) 
AS 
BEGIN 
    EXEC (@somesql) 
END 

Sẽ không làm việc, bởi vì mối quan hệ sơ đồ bị mất bên trong EXEC.

Trong khi điều này:

CREATE PROCEDURE schema_a.SP 
AS 
BEGIN 
    SELECT * FROM tbl -- Will use schema_a.tbl first 
END 

CREATE PROCEDURE schema_b.SP 
AS 
BEGIN 
    SELECT * FROM tbl -- Will use schema_b.tbl first 
END 

hoạt động tốt.

Tương tự:

EXEC ('EXEC schema_a.SP') 

sẽ rõ ràng là hoạt động tốt.

+0

Vẫn là một kludge, nhưng tôi thích nó hơn là tạo thêm người dùng. –

+0

Không hoạt động. Nó nhặt bàn trong dbo khi tôi thử nó. –

+0

Tôi sẽ đi với EXECUTE AS như trong câu trả lời của RBArryYoung vì bạn đã sử dụng SQL động. Lý do mối quan hệ lược đồ không hoạt động với bạn là khi bạn nhấn vào exec, bạn đang mất bối cảnh của lược đồ từ SP gọi exec, giống như nó mất đi mọi thứ khác. –

0

Chưa được thử, nhưng: bạn có thể kết hợp dữ liệu của các lược đồ khác nhau vào một chế độ xem và thêm cột gọi tên lược đồ không?

CREATE VIEW AllPosts AS 
    SELECT Data1, Data2, 'Sept09' AS Partition FROM SO_Sept09..Posts 
    UNION ALL 
    SELECT Data1, Data2, 'Oct09' AS Partition FROM SO_Oct09..Posts 
    ... 

SELECT * FROM AllPosts WHERE Partition = 'Sept09' 
SELECT * FROM dbo.AllPosts('Sept09') -- if use table-valued function instead 
+0

Đó là một suy nghĩ, nhưng nó sẽ phá vỡ rất nhiều chỉ mục của tôi. –

+0

Bạn có thể lập chỉ mục lượt xem, mặc dù có toàn bộ lưu ý. http://msdn.microsoft.com/en-us/library/dd171921.aspx http://msdn.microsoft.com/en-us/library/ms191432.aspx –

11

Có một số cách để thực hiện việc này ở nhiều nơi khác nhau tại đây, nhưng không hoàn toàn.Các cách để làm điều này là:

  1. Thực hiện một độc đáo đăng nhập người dùng & cho mỗi schema

  2. Make những người sử dụng các chủ sở hữu của mỗi giản đồ khác nhau.

  3. Đặt từng lược đồ mặc định của người dùng đó làm giản đồ mà họ sở hữu.

  4. Sử dụng cú pháp EXECUTE ('sql commands') AS USER = 'schema-owner' để thực thi các lệnh SQL của bạn trong ngữ cảnh của lược đồ mặc định đó.

Các kịch bản sau đây chứng tỏ điều này:

--====== Create the Login for the User: 
CREATE LOGIN [UserTest1] WITH PASSWORD='whatever', DEFAULT_DATABASE=[TestUsers], DEFAULT_LANGUAGE=[us_english] 
GO 

--====== Make a User for the Login: 
CREATE USER [UserTest1] FOR LOGIN [UserTest1] 
GO 

--====== Make a Schema owned by the User and default to it: 
--  (I assume that you already have the schemas) 
CREATE SCHEMA [UserTest1] AUTHORIZATION [UserTest1] 
GO 
ALTER USER [UserTest1] WITH DEFAULT_SCHEMA=[UserTest1] 
GO 

--====== Make a sProc in dbo 
CREATE PROCEDURE [dbo].[TestSchema_Exec] AS 
    SELECT 'executing in schema [dbo]' 
GO 
--====== Make a similar sProc in New Schema 
CREATE PROCEDURE [UserTest1].[TestSchema_Exec] AS 
    SELECT 'executing in schema [UserTest1]' 
GO 

--========= Demonstrate that we can switch Default Schemas: 
EXEC('TestSchema_Exec') 

EXEC('TestSchema_Exec') AS USER = 'UserTest1' 
0

Được rồi, tôi có một cách mới để làm điều này có thể làm việc tốt hơn một chút cho tôi. Đó là một biến thể trong nhận xét của tôi về câu trả lời của Michael Petrotta:

Nhưng nó cho tôi ý tưởng có thể có nhiều người dùng và chọn chuỗi kết nối khi đang bay.

Điều tôi sẽ làm là chỉ có một người dùng để thực hiện các truy vấn này, nhưng tôi sẽ hoán đổi chuỗi kết nối khi đang bay để chỉ định Danh mục ban đầu chính xác.

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