- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
有没有一种方法可以省略存储过程中使用的对象模式,这些对象不绑定(bind)到存储过程的模式,而是以相同存储过程产生不同结果的方式使用记录的模式不同模式中的用户?
为了更好地理解我正在尝试做的事情,下面我将尝试更好地解释。
假设有以下数据库:
CREATE TABLE [dbo].[SampleTable01] (...)
CREATE TABLE [dbo].[SampleTable02] (...)
CREATE TABLE [dbo].[SampleTable03] (...)
CREATE TABLE [dbo].[SampleTable04] (...)
在这个数据库中,表名后面的数字代表表的所有者(这是一个遗留系统,我无法更改)。
为了将其集成到 .net Entity Framework 中,我提供了一个在不同模式中创建同义词的解决方案,因此更改连接字符串我可以更改使用的对象,而无需更改我的数据库上下文或我的编程逻辑。
像这样。
CREATE SCHEMA [s01]
CREATE SYNONYM [s01].[SampleTable] FOR [dbo].[SampleTable01]
...
CREATE SCHEMA [s04]
CREATE SYNONYM [s04].[SampleTable] FOR [dbo].[SampleTable04]
此解决方案运行良好,但我需要复制所有使用的存储过程,因为存储过程绑定(bind)到特定对象。
当我创建以下存储过程时:
CREATE PROCEDURE [dbo].[usp_SampleProc] AS
SELECT * FROM [SampleTable]
存储过程将产生错误,因为 [SampleTable]
不存在于架构 [dbo]
中。
我正在做的是复制存储过程以匹配登录用户的模式。
所以我这样做:
CREATE PROCEDURE [s01].[usp_SampleProc] AS
SELECT * FROM [s01].[SampleTable]
...
CREATE PROCEDURE [s04].[usp_SampleProc] AS
SELECT * FROM [s04].[SampleTable]
[s01]
模式中的用户将从 [s01].[SampleTable]
和 [s04]
模式中的用户获取值将从 [s04].[SampleTable]
获取值,在执行 [usp_SampleProc]
时未指定架构,这是我的预期结果。
到目前为止一切顺利,这在我的真实场景中并没有产生效果。我有上千个表、数百个过程和几十个模式(我知道这很丑陋,但我将遗留系统与 .net 集成,到目前为止,这是我得出的最佳解决方案)。
那么,问题又来了:
有没有一种方法可以省略存储过程中使用的对象模式,并且这些对象不绑定(bind)到存储过程的模式,而是以相同存储过程生成的方式绑定(bind)到登录用户的模式不同模式下用户的不同结果?
最佳答案
这是我知道的两种方法来做我想做的事情。
这两种方式对开发人员都是透明的,因此他们不需要了解解决方案的复杂性。
下面我创建了一个每个人都可以使用的示例:
原始遗留数据库创建:保持不变,因为遗留应用程序仍在使用数据库。
CREATE TABLE [dbo].[SampleTable01] (
value varchar(100)
)
INSERT INTO [dbo].[SampleTable01] VALUES ('[dbo].[SampleTable01]')
CREATE TABLE [dbo].[SampleTable02] (
value varchar(100)
)
INSERT INTO [dbo].[SampleTable02] VALUES ('[dbo].[SampleTable02]')
CREATE TABLE [dbo].[SampleTable03] (
value varchar(100)
)
INSERT INTO [dbo].[SampleTable03] VALUES ('[dbo].[SampleTable03]')
CREATE TABLE [dbo].[SampleTable04] (
value varchar(100)
)
INSERT INTO [dbo].[SampleTable04] VALUES ('[dbo].[SampleTable04]')
GO
我的应用程序使用的用户和架构分离:这些是很多重复的代码,但将由应用程序设置生成。
CREATE SCHEMA [S01]
GO
CREATE SCHEMA [S02]
GO
CREATE SCHEMA [S03]
GO
CREATE SCHEMA [S04]
GO
CREATE USER USER_S01 WITHOUT LOGIN WITH DEFAULT_SCHEMA = S01
GO
CREATE USER USER_S02 WITHOUT LOGIN WITH DEFAULT_SCHEMA = S02
GO
CREATE USER USER_S03 WITHOUT LOGIN WITH DEFAULT_SCHEMA = S03
GO
CREATE USER USER_S04 WITHOUT LOGIN WITH DEFAULT_SCHEMA = S04
GO
CREATE SYNONYM [S01].[SampleTable] FOR [dbo].[SampleTable01]
CREATE SYNONYM [S02].[SampleTable] FOR [dbo].[SampleTable02]
CREATE SYNONYM [S03].[SampleTable] FOR [dbo].[SampleTable03]
CREATE SYNONYM [S04].[SampleTable] FOR [dbo].[SampleTable04]
GO
GRANT DELETE ON SCHEMA::[S01] TO [USER_S01]
GRANT EXECUTE ON SCHEMA::[S01] TO [USER_S01]
GRANT INSERT ON SCHEMA::[S01] TO [USER_S01]
GRANT REFERENCES ON SCHEMA::[S01] TO [USER_S01]
GRANT SELECT ON SCHEMA::[S01] TO [USER_S01]
GRANT UPDATE ON SCHEMA::[S01] TO [USER_S01]
GRANT EXECUTE ON SCHEMA::[S01] TO [USER_S01]
GO
GRANT DELETE ON SCHEMA::[S02] TO [USER_S02]
GRANT EXECUTE ON SCHEMA::[S02] TO [USER_S02]
GRANT INSERT ON SCHEMA::[S02] TO [USER_S02]
GRANT REFERENCES ON SCHEMA::[S02] TO [USER_S02]
GRANT SELECT ON SCHEMA::[S02] TO [USER_S02]
GRANT UPDATE ON SCHEMA::[S02] TO [USER_S02]
GRANT EXECUTE ON SCHEMA::[S02] TO [USER_S02]
GO
GRANT DELETE ON SCHEMA::[S03] TO [USER_S03]
GRANT EXECUTE ON SCHEMA::[S03] TO [USER_S03]
GRANT INSERT ON SCHEMA::[S03] TO [USER_S03]
GRANT REFERENCES ON SCHEMA::[S03] TO [USER_S03]
GRANT SELECT ON SCHEMA::[S03] TO [USER_S03]
GRANT UPDATE ON SCHEMA::[S03] TO [USER_S03]
GRANT EXECUTE ON SCHEMA::[S03] TO [USER_S03]
GO
GRANT DELETE ON SCHEMA::[S04] TO [USER_S04]
GRANT EXECUTE ON SCHEMA::[S04] TO [USER_S04]
GRANT INSERT ON SCHEMA::[S04] TO [USER_S04]
GRANT REFERENCES ON SCHEMA::[S04] TO [USER_S04]
GRANT SELECT ON SCHEMA::[S04] TO [USER_S04]
GRANT UPDATE ON SCHEMA::[S04] TO [USER_S04]
GRANT EXECUTE ON SCHEMA::[S04] TO [USER_S04]
GO
解决方案 1(我的选择):在不同的模式中使用相同的过程名称。每个用户一个过程(有自己的模式)。
CREATE PROCEDURE [S01].[usp_SampleProc]
AS
SELECT * FROM [SampleTable]
GO
CREATE PROCEDURE [S02].[usp_SampleProc]
AS
SELECT * FROM [SampleTable]
GO
CREATE PROCEDURE [S03].[usp_SampleProc]
AS
SELECT * FROM [SampleTable]
GO
CREATE PROCEDURE [S04].[usp_SampleProc]
AS
SELECT * FROM [SampleTable]
GO
解决方案 2: 使用动态创建,因为在执行时表引用将被解析为用户架构中的同义词。
GRANT EXECUTE ON SCHEMA::[dbo] TO [USER_S01]
GRANT EXECUTE ON SCHEMA::[dbo] TO [USER_S02]
GRANT EXECUTE ON SCHEMA::[dbo] TO [USER_S03]
GRANT EXECUTE ON SCHEMA::[dbo] TO [USER_S04]
GO
CREATE PROCEDURE [dbo].[usp_SampleProc]
AS
exec(N'SELECT * FROM [SampleTable]')
GO
执行:两种解决方案完全相同。
EXECUTE AS USER = 'USER_S01'
EXEC [usp_SampleProc]
REVERT;
EXECUTE AS USER = 'USER_S02'
EXEC [usp_SampleProc]
REVERT;
EXECUTE AS USER = 'USER_S03'
EXEC [usp_SampleProc]
REVERT;
EXECUTE AS USER = 'USER_S04'
EXEC [usp_SampleProc]
REVERT;
选择理由:我不希望开发人员简化程序的创建和测试。并解决生产中发生的错误。按照我决定使用的方式,所有模式的过程都将完全相同。因此,只需记录该问题并为所有模式解决该问题,就可以轻松测试该模式中发生的问题。
该解决方案的缺点是我无法将模式放入过程内的表中。所以这将是一个轻微的性能损失。
关于sql - 动态使用 T-SQL 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12976131/
我对这个错误很困惑: Cannot implicitly convert type 'System.Func [c:\Program Files (x86)\Reference Assemblies\
考虑这段代码: pub trait Hello { fn hello(&self); } impl Hello for Any { fn hello(&self) {
问题很简单。是否可以构造这样一个类型 T,对于它下面的两个变量声明会产生不同的结果? T t1 = {}; T t2{}; 我已经研究 cppreference 和标准一个多小时了,我了解以下内容:
Intellij idea 给我这个错误:“Compare (T, T) in Comparator cannot be applied to (T, T)” 对于以下代码: public class
任何人都可以告诉我 : n\t\t\t\t\n\t\t\t 在以下来自和 dwr 服务的响应中的含义和用途是什么. \r\n\t\t\t \r\n\t\t\t
让 T 成为一个 C++ 类。 下面三个指令在行为上有什么区别吗? T a; T a(); T a = T(); T 为不带参数的构造函数提供了显式定义这一事实是否对问题有任何改变? 后续问题:如果
Rust中的智能指针是什么 智能指针(smart pointers)是一类数据结构,是拥有数据所有权和额外功能的指针。是指针的进一步发展 指针(pointer)是一个包含内存地
比如我有一个 vector vector > v={{true,1},{true,2},{false,3},{false,4},{false,5},{true,6},{false,7},{true,8
我有一个来自 .xls 电子表格的数据框,我打印了 print(df.columns.values) 列,输出包含一个名为:Poll Responses\n\t\t\t\t\t。 我查看了 Excel
This question already has answers here: What are good reasons for choosing invariance in an API like
指针类型作为类型前缀与在类型前加斜杠作为后缀有什么区别。斜线到底是什么意思? 最佳答案 语法 T/~ 和 T/& 基本上已被弃用(我什至不确定编译器是否仍然接受它)。在向新向量方案过渡的初始阶段,[T
我正在尝试找到一种方法来获取模板参数的基类。 考虑以下类: template class Foo { public: Foo(){}; ~Foo(){};
这是一个让我感到困惑的小问题。我不知道如何描述它,所以只看下面的代码: struct B { B() {} B(B&) { std::cout ::value #include
为什么有 T::T(T&) 而 T::T(const T&) 更适合 copy ? (大概是用来实现move语义的???) 原始描述(被melpomene证明是错误的): 在C++11中,支持了一种新
在 Java 7 中使用 eclipse 4.2 并尝试实现 List 接口(interface)的以下方法时,我收到了警告。 public T[] toArray(T[] a) { ret
假设有三个函数: def foo[T](a:T, b:T): T = a def test1 = foo(1, "2") def test2 = foo(List(), ListBuffer()) 虽
我对柯里化(Currying)和非柯里化(Currying)泛型函数之间类型检查的差异有点困惑: scala> def x[T](a: T, b: T) = (a == b) x: [T](a: T,
考虑一个类A,我如何编写一个具有与相同行为的模板 A& pretty(A& x) { /* make x pretty */ return x; } A pretty(A&& x) {
Eclipse 表示由于泛型类型橡皮擦,类型参数不允许使用 instanceof 操作。 我同意在运行时不会保留任何类型信息。但是请考虑以下类的通用声明: class SomeClass{ T
在 C++14 中: 对于任何整数或枚举类型 T 以及对于任何表达式 expr: 有没有区别: struct S { T t { expr }; }; 和 struct S { T t = { exp
我是一名优秀的程序员,十分优秀!