有没有办法在sql server中创建子数据库作为一种子文件夹?
我正在创建一个应用程序,其中有主数据库,其他数据存储在辅助数据库中。辅助数据库遵循“插件”方法。我使用 SQL Server。
应用程序的简单安装将只具有主数据库,而作为一种选择,可以激活更多“插件”,并且对于每个插件都会有一个新数据库。
现在我做出这个选择的原因是因为我必须使用现有的遗留系统,这是我能想到的实现插件系统的最明智的事情。
MainDB 和 Plugins DB 具有完全相同的架构(基本上 Plugins DB 有一些“特殊内容”,一些可以用作一种模板的重要数据 - 例如,在应用程序中考虑信件模板)。插件数据库以只读模式使用,它们是“内容存储库”。 “聪明”的是,主应用程序也可以由“插件编写者”使用,他们只需编写一个插入内容的数据库,然后通过备份数据库,他们创建一个潜在的插件(这就是为什么所有数据库都具有相同的插件)模式)。
这些插件数据库是从互联网下载的,因为每次完整的插件数据库被销毁并创建一个同名的新插件数据库时,都会有可用的内容升级。这是为了简单起见,甚至是因为该数据库的大小通常很小。
现在这可行了,无论如何,我更喜欢以树结构来组织数据库,这样我就可以强制插件数据库成为主应用程序数据库的“子数据库”。
作为一种解决方法,我正在考虑使用命名规则,例如:
ApplicationDB (对于主应用程序 DB)
ApplicationDB_PlugIn_N (对于第 N 个插件 DB)
当我搜索插件 1 时,如果找不到,我会尝试连接到 ApplicationDB_PlugIn_1数据库我提出了一个错误。例如,如果某些 DBA 重命名 ApplicationDB_Plugin_1,则可能会发生这种情况。
因此,由于这些插件数据库实际上依赖于 ApplicationDB,只有我试图“执行子文件夹技巧”。
谁能建议一种方法来做到这一点?您能评论一下我上面描述的这种自制插件方法吗?
添加信息(开始赏金后):
在MainDB中,我计划将连接信息存储到所有插件数据库。基本上它是数据库名称,因为我设计系统的方式是即使我使用多个 sql 服务器登录名来访问 MainDB,在幕后也是单个用户(通常是“sa”或具有管理员权限的其他用户)。
所以基本上,如果我需要查询多个数据库,我将使用数据库名称来区分插件,我不需要在数据库表中显式创建名为 PluginID 的字段。
所以不知何故它的工作原理是这样的,在主数据库中我存储插件数据库名称。所以我知道插件的名称,所以如果我想查询所有插件中的所有枪支,我会这样做:
select * from ApplicationDB_Plugin_1.dbo.weapons where weapon_type = 'gun'
union
select * from ApplicationDB_Plugin_2.dbo.weapons where weapon_type = 'gun'
union
select * from ApplicationDB_Plugin_3.dbo.weapons where weapon_type = 'gun'
所以“技巧”是使用数据库名称来区分插件。现在这项工作,但对我来说似乎有点“肮脏”。我的问题是“您能想到更好的方法吗?”
I am creating an application where there is main DB and where other data is stored in secondary databases. The secondary databases follow a "plugin" approach. I use SQL Server.
A simple installation of the application will just have the mainDB, while as an option one can activate more "plug-ins" and for every plug-in there will be a new database.
Now why I made this choice is because I have to work with an exisiting legacy system and this is the smartest thing I could figure to implement the plugin system.
MainDB and Plugins DB have exactly the same schema (basically Plugins DB have some "special content", some important data that one can use as a kind of template - think to a letter template for example - in the application). Plugin DBs are so used in readonly mode, they are "repository of content". The "smart" thing is that the main application can also be used by "plugin writers", they just write a DB inserting content, and by making a backup of the database they creaetd a potential plugin (this is why all DBs has the same schema).
Those plugins DB are downloaded from internet as there is a content upgrade available, every time the full PlugIn DB is destroyed and a new one with the same name is creaetd. This is for simplicity and even because the size of this DBs is generally small.
Now this works, anyway I would prefer to organize the DBs in a kind of Tree structure, so that I can force the PlugIn DBs to be "sub-DBs" of the main application DB.
As a workaround I am thinking of using naming rules, like:
ApplicationDB (for the main application DB)
ApplicationDB_PlugIn_N (for the N-th plugin DB)
When I search for plugin 1 I try to connect to ApplicationDB_PlugIn_1, if I don't find the DB i raise an error. This situation can happen for example if som DBA renamed ApplicationDB_Plugin_1.
So since those Plugin DBs are really dependant on ApplicationDB only I was trying to "do the subfolder trick".
Can anyone suggest a way to do this? Can you comment on this self-made plugin approach I decribed above?
ADDED INFO (AFTER STARTING THE BOUNTY):
In the MainDB I plan to store the connection info to all the plugin DBs. Basically it is the database name, since I deigned the sytem in a way that even if I use multiple sql server logins to access the MainDB, behind the scenes a single user (typically "sa" or another user with admin privileges).
So basically if I need to query multiple databases I will use the database name to distinguish between plugins, I don't need to explicitly create fileds called PluginID in the database tables.
So somehow it works like this, in the main DB I store the plugin DB names. So I know the name of the plugins, so if I want to query all the GUNS from all plugins i will do something like this:
select * from ApplicationDB_Plugin_1.dbo.weapons where weapon_type = 'gun'
union
select * from ApplicationDB_Plugin_2.dbo.weapons where weapon_type = 'gun'
union
select * from ApplicationDB_Plugin_3.dbo.weapons where weapon_type = 'gun'
so the "trick" is using the dbname to distinguish between plugins. Now this work, but it seems a little "dirty" to me. My question is "IS THERE A BETTER APPROACH YOU CAN ENVISION?"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用模式:
You can use schemas:
如果架构相同,您是否可以向现有表中添加一些内容,以便您可以知道某些数据来自插件 1,而其他数据来自插件 2?您将来可能会发现需要进行“跨插件查询”?
If the schemas are identical, can you add something to the existing tables so you can tell that some data is from plug-in-1 while other data is from plug-in-2? You might find a need in the future to do 'cross-plug-in queries'?
我可以理解您是如何得出当前的解决方案的。保持数据库独立可以明确哪些数据属于每个插件,并保持关注点独立。
虽然它通过简单的组织提供了清晰度,但这种方法有一些相当显着的缺点:
不会面临为每个插件连接到不同的数据库。数据库服务器将运行查询 N 次来查询 N 个插件,因为它必须针对每个插件的单独数据库运行每个查询。
引用完整性不容易在多个数据库(如果有的话)之间强制执行,因此您的数据很可能会变得不一致。
引用完整性不容易在多个数据库(如果有的话)
灵活性和“活力”降低:创建新数据库是一项相当繁重的操作,因此添加新插件变得相当繁重。
灵活性和“活力”降低
最后,处理架构更改将很困难 - 如果您有一个尚未更新到最新架构的插件,那么它不能在此方案中使用,因为假定所有数据库都具有相同的结构。
我建议采用混合方法:每个插件继续维护自己的数据库,可以在运行时下载和加载,但不是将应用程序和插件保存在单独的数据库中,而是将插件数据和应用程序数据复制到复合数据库。复合数据库可以在启动时构建,或者在插件集更改时构建,或者在新的插件版本可用时构建。这是可行的,因为您提到每个插件数据库只能读取,不能更新。 (可以重建数据库,以便保留复合数据库中的应用程序数据。)
当应用程序数据和插件中的数据集成到一个数据库中时,您可以避免上述问题:
数据库服务器只执行一个查询而不是每个插件执行一个查询
引用完整性是可执行的,因为所有数据都维护在一个数据库中。
引用完整性
最后,也是最重要的,在我看来 - 管理架构更改成为可能。如果有插件尚未实现最新的架构更改,则合并过程可以在将插件数据复制到复合数据库(始终使用最新架构)时调整使用旧架构存储的数据。例如,在复制时使用旧模式的插件,可以为新列添加默认值,可以适应结构的变化,可以删除列/行等。还可以向插件开发人员提供相同的“模式升级”代码以允许他们升级他们的插件架构。
合并过程还可以构建一个“installed_plugins”表,列出复制到复合数据库的所有插件。该表包含有关每个插件的元数据,例如插件更新日期、添加时间、唯一插件 ID 等。
那么,复合数据库是什么样子的:
我更喜欢第二种选择。但是,当所有插件数据存储在一起时,如何知道每一行来自哪个插件?同样有两个选项:
为简单起见,我的偏好是 1,添加 ID 列。由于复合数据库中的表是由脚本或程序构建的,因此任一方案都易于实现,因此主要与偏好或性能需求有关,或者合并数据库对核心数据表使用与合并数据库相同的架构是否重要。原始应用程序数据库。
我认为将数据合并在一起是正确的方法,可以减少痛苦、更容易维护、灵活性和更高的性能。但是,如果您仍然有强烈的动机将数据保存在单独的表中,那么至少将它们保存在同一个数据库中,并使用表名前缀或更好的模式名称来保持插件数据命名空间分离。
祝你好运,无论你选择哪种方式!
I can understand how you arrived at your current solution. Keeping the databases separate makes it clear which data belongs to each plugin, and keeps concerns separate.
Although it offers clarity through a simple organization, this approach has some fairly significant downsides:
Connecting to a different db for each plugin is not going to be face. The database server will have a run a query N times to query N plugins, since it has to run each query against a separate database for each plugin.
Referential integrity is not easily enforcable across several databases (if at all) so it's quite likely your data may become inconsistent.
reduced flexibility and "dynamism": creating a new database quite a heavy operation, and so adding a new plugin becomes quite a heavy operation.
Finally, dealing with schema changes will be difficult - if you have a plugin that hasn't been updated to the latest schema, then it cannot be used in this scheme since all databases are assumed to have the same structure.
I would suggest a hybrid approach: each plugin continues to maintain it's own database which can be downloaded, and loaded at runtime, but rather than keeping the application and plugins in separate databases, the plugin data and application ddata are copied to a composite database. The composite database can be built at startup, or when the set of plugins changes, or as a new plugin version becomes available. This is workable since you mention each plugin database is only read, and not updated. (Rebuilding the database can be done so that the application data in the composite database is preserved.)
When the application data and the data from the plugins are integrated into one database you avoid the problems above:
the database server executes just one query rather than one per plugin
referential integrity is enforceable since all the data is maintained in one database.
finally, and most importantly, in my view - managing schema changes becomes possible. If there are plugins that haven't implemented your latest schema changes, the merging process can adapt data stored using the old schema while it is copying the plugin data to the composite dataabase (which always uses the latet schema.) For example, while copying a plugin using the old schema, default values can be added for new columns, changes in structure can be accomodated, columns/rows can be deleted etc. The same "schema upgrade" code can also be given to plugin developers to allow them to upgrade their plugin schema.
The merge process could also build an "installed_plugins" table listing all the plugins that are copied to the composite database. The table contains metadata about each plugin such as date of plugin update, time added, unique plugin id etc.
So, what does the composite database look like:
My preference is for the second option. But with all plugin data stored together, how to know which plugin each row comes from? Again there are two options:
For simplicity, my preference would be for 1, adding an ID column. Since the tables in the composite database are built by a script or program, either scheme is simple to implement, and so it's mostly about preference or performance needs or whether it's important that the merge database uses the same schema for the core data tables as the original application database.
I feel that merging the data together is the right approach, for less pain, easier maintainance, flexibility and greater performance. But if you still have strong motives for keeping the data in separate tables, then at least keep them in the same database, and use either table name prefix, or better, schema names to keep the plugin data namespaces separate.
Good luck, which ever way you choose!