如何查询数据库模式是不是存在

Posted

技术标签:

【中文标题】如何查询数据库模式是不是存在【英文标题】:How do I query if a database schema exists如何查询数据库模式是否存在 【发布时间】:2010-09-18 13:40:22 【问题描述】:

作为构建过程的一部分,我们在将代码部署到 4 个不同的环境时运行数据库更新脚本。此外,由于相同的查询将被添加到我们将一个版本投入生产之前,它必须能够在给定的数据库上运行多次。像这样:

IF NOT EXISTS (SELECT * FROM sys.tables WHERE object_id = OBJECT_ID(N'[Table]'))
BEGIN
  CREATE TABLE [Table]
  (...)
END

目前我在部署/构建脚本中有一个创建模式语句。在哪里查询架构是否存在?

【问题讨论】:

请考虑更改接受的答案。你接受的答案不可能真的对你有用。 【参考方案1】:

你在找sys.schemas吗?

IF NOT EXISTS (SELECT * FROM sys.schemas WHERE name = 'jim')
BEGIN
EXEC('CREATE SCHEMA jim')
END

注意CREATE SCHEMA 必须在自己的批处理中运行(根据the answer below)

【讨论】:

这在 SQL 2008 中不起作用,因为 CREATE SCHEMA 需要成为批处理中的第一个语句,请参阅 vfilby 帖子以了解解决方法 你可以使用'Select 1 from sys.schemas'来提高性能。 @vijaysylvester 不,这是一个神话。 SQL Server 优化了列列表,因此您放在那里的内容并不重要。完全无视。想要证据?把SELECT 1/0... 我已将此答案更新为不正确(即使用***.com/a/521271/2688下方的脚本) 虽然 * vs 1 vs 1/0 可能不会产生任何性能差异,但在某些情况下它确实会产生差异。从安全的角度来看,所有 3 个选项都要求您有权访问所有列,而命名特定列会导致仅检查查询中实际命名的列。因此,如果查询中任何表的任何列被拒绝,则“select col-with-access ...”会成功,而“select 1 ...”不会成功。【参考方案2】:

@bdukes 在确定架构是否存在方面是正确的,但上面的语句在 SQL Server 2005 中不起作用。CREATE SCHEMA <name> 需要在自己的批处理中运行。一种解决方法是在 exec 中执行 CREATE SCHEMA 语句。

这是我在构建脚本中使用的:

IF NOT EXISTS (SELECT 1 FROM sys.schemas WHERE name = '<name>')
BEGIN
    -- The schema must be run in its own batch!
    EXEC( 'CREATE SCHEMA <name>' );
END

【讨论】:

就像一个魅力!这甚至可以让我把我的打印语句和所有内容。【参考方案3】:

只是为了额外“防御性”,以下版本会生成类型转换错误,以说明 > 1 匹配 Schema 的可能性(但不太可能)类似于验证代码的常见方式故意抛出异常,因为我相信这是好的,并且我相信它是“最佳实践”来解释所有可能的返回结果,但不太可能,即使它只是产生一个致命的异常,因为停止处理的已知效果通常比未知好未捕获错误的级联效应。因为这不太可能,所以我认为不值得麻烦单独使用Count check + ThrowTry-Catch-Throw 来生成更用户友好的致命错误,但仍然是致命错误尽管如此。

SS 2005-:

declare @HasSchemaX bit
set @HasSchemaX = case (select count(1) from sys.schemas where lower(name) = lower('SchemaX')) when 1 then 1 when 0 then 0 else 'ERROR' end

SS 2008+:

declare @HasSchemaX bit = case (select count(1) from sys.schemas where lower(name) = lower('SchemaX')) when 1 then 1 when 0 then 0 else 'ERROR' end

然后:

if @HasSchemaX = 1
begin
   ...
end -- if @HasSchemaX = 1

【讨论】:

我想当您使用区分大小写的排序规则时,可能会有多个匹配的架构,但是您的“错误处理”会导致以下错误:转换 varchar 值时转换失败'ERROR' 到数据类型 int。 @Stijn:这是“设计”,类似于验证代码经常故意ThrowException。就像您说的那样,这不是“可能”发生的,所以恕我直言,不值得整个Try-Catch 或单独的Count 检查以生成更用户友好的致命错误,但无论如何,我可能想要一个致命的错误。我相信并且我相信这是“最佳实践”来解释所有可能的返回结果,但不太可能,即使它只是产生一个致命的异常,因为停止处理的已知效果通常比未捕获的未知级联效果更好错误。 听起来不错,我不确定是否是故意的 :) 您的回答可能会受益于一些额外的解释,就像您在评论中给出的那样。 @Stijn:我最讨厌的是不检查 SelectInsertUpdateDelete 是否返回/受影响的常见“最佳实践”多于 少于预期的行数,但不太可能。即使有(有)UniqueIndex'es 当前确保预期的 #(即 1)行将被返回/影响,这可能会改变(意外或(短视)“故意”)未来。【参考方案4】:

这是旧的,所以我不得不添加:对于 SQL SERVER 2008+ 这些都可以工作(对于选择部分),然后使用 EXECUTE('CREATE SCHEMA &lt;name&gt;') 在否定结果上实际创建它。

DECLARE @schemaName sysname = 'myfunschema';
-- shortest
If EXISTS (SELECT 1 WHERE SCHEMA_ID(@schemaName) IS NOT NULL)
PRINT 'YEA'
ELSE
PRINT 'NOPE'

SELECT DB_NAME() AS dbname WHERE SCHEMA_ID(@schemaName) IS NOT NULL -- nothing returned if not there

IF NOT EXISTS ( SELECT  top 1 *
                FROM    sys.schemas
                WHERE   name = @schemaName )
PRINT 'WOOPS MISSING'
ELSE
PRINT 'Has Schema'

SELECT SCHEMA_NAME(SCHEMA_ID(@schemaName)) AS SchemaName1 -- null if not there otherwise schema name returned

SELECT SCHEMA_ID(@schemaName) AS SchemaID1-- null if not there otherwise schema id returned


IF EXISTS (
    SELECT sd.SchemaExists 
    FROM (
        SELECT 
            CASE 
                WHEN SCHEMA_ID(@schemaName) IS NULL THEN 0
                WHEN SCHEMA_ID(@schemaName) IS NOT NULL THEN 1
                ELSE 0 
            END AS SchemaExists
    ) AS sd
    WHERE sd.SchemaExists = 1
)
BEGIN
    SELECT 'Got it';
END
ELSE
BEGIN
    SELECT 'Schema Missing';
END

【讨论】:

IF schema_id ('MySchemaName') IS NULL 效果很好,似乎比接受的答案更方便。 同意@BradC。对于那些遇到异常的人:IF SCHEMA_ID('out') IS NULL EXEC('CREATE SCHEMA [out] AUTHORIZATION [out]');【参考方案5】:

如果组件的布局允许,这也可以。

IF EXISTS (SELECT 1 FROM sys.schemas WHERE name = 'myschema') SET NOEXEC ON 走 CREATE SCHEMA 架构 走 SET NOEXEC OFF -- 如果需要进一步处理。 走

【讨论】:

以上是关于如何查询数据库模式是不是存在的主要内容,如果未能解决你的问题,请参考以下文章

excel如何查询一组数据在另一个表格中是不是存在同一组数据?

在SQL中如何快速查询某条记录在所有表中是不是存在?

如何查询行中是不是存在值将值添加到另一个字段?

django怎么判断数据库的记录是不是存在

php 查询数据库表 判断 某值是不是存在

如何使用geofire查询检查10公里半径内是不是存在firebase用户