Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server-选择满足特定条件的列?_Sql_Sql Server 2008 - Fatal编程技术网

SQL Server-选择满足特定条件的列?

SQL Server-选择满足特定条件的列?,sql,sql-server-2008,Sql,Sql Server 2008,我的列只能包含三个值或var字符-经济型、基本型和豪华型。我想选择一行,只显示那些包含奢侈品的列。问题是有很多这样的专栏——大约50篇。我不想在select查询中键入所有这些列的名称。有没有一个更短更简单的替代方案?我应该使用哪个查询 我在想这样的问题这是个假问题- 表格结构- rowId | Column1 | Column2 | Column3..... 我已经为您创建了一个存储过程 此过程检查MSSQL元以构建一个动态SQL字符串,该字符串返回一个结果,该结果包含指定表的列名N及其值V,

我的列只能包含三个值或var字符-经济型、基本型和豪华型。我想选择一行,只显示那些包含奢侈品的列。问题是有很多这样的专栏——大约50篇。我不想在select查询中键入所有这些列的名称。有没有一个更短更简单的替代方案?我应该使用哪个查询

我在想这样的问题这是个假问题-

表格结构-

rowId | Column1 | Column2 | Column3.....

我已经为您创建了一个存储过程

此过程检查MSSQL元以构建一个动态SQL字符串,该字符串返回一个结果,该结果包含指定表的列名N及其值V,以及从中检索该值的对应行键K

执行此操作时,结果存储在名为ColumnsByValue的全局临时表中,然后可以直接查询该表

通过执行以下脚本,创建GetColumnsByValue存储过程:

-- =============================================
-- Author:      Ben Roberts (sepster@internode.on.net)
-- Create date: 22 Mar 2013
-- Description: Returns the names of columns that contain the specified value, for a given row
-- =============================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID ( 'dbo.GetColumnsByValue', 'P' ) IS NOT NULL 
    DROP PROCEDURE dbo.GetColumnsByValue;
GO
CREATE PROCEDURE dbo.GetColumnsByValue
    -- Add the parameters for the stored procedure here
    @idColumn sysname,
    @valueToFind nvarchar(255), 
    @dbName sysname,
    @tableName sysname,
    @schemaName sysname,
    @debugMode int = 0

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from interfering with SELECT statements.
    SET NOCOUNT ON;

    DECLARE @SQL nvarchar(max);
    DECLARE @SQLUnion nvarchar(max);
    DECLARE @colName sysname;
    DECLARE @dbContext nvarchar(256);
    DECLARE @Union nvarchar(10);

    SELECT @dbContext = @dbName + '.' + @schemaName + '.sp_executeSQL';
    SELECT @SQLUnion = '';
    SELECT @Union = '';

    IF OBJECT_ID ( 'tempdb..##GetColumnsByValueIgnoreList') IS NULL -- no columns to ingore have been specified, need to create an empty list.
    BEGIN
        CREATE TABLE ##GetColumnsByValueIgnoreList (column_name nvarchar(255));
    END

    DECLARE DBcursor CURSOR FOR
        SELECT 
            COLUMN_NAME
        FROM 
            INFORMATION_SCHEMA.COLUMNS
        WHERE 
            TABLE_NAME = @tableName 
            AND 
            TABLE_SCHEMA = @schemaName;

    OPEN DBcursor; 
        FETCH DBcursor INTO @colName;
        WHILE (@@FETCH_STATUS = 0)
        BEGIN
            IF (
                @colName != @idColumn
                AND
                @colName NOT IN (SELECT column_name FROM ##GetColumnsByValueIgnoreList)
            )
            BEGIN
                SELECT @SQL = 'SELECT '+@idColumn+' as K, '''+@colName+''' as N, ' +@colName+ ' as V FROM ' + @dbName + '.' + @schemaName + '.' + @tableName;
                --PRINT @SQL;
                SELECT @SQLUnion = @SQL + @Union + @SQLUnion;
                SELECT @Union = ' UNION ';
            END
            FETCH  DBcursor INTO @colName;
        END; -- while
    CLOSE DBcursor; DEALLOCATE DBcursor;

    IF (@debugMode != 0)
        BEGIN
            PRINT @SQLUnion;
            PRINT @dbContext;
        END
    ELSE
        BEGIN
            -- Delete the temp table if it has already been created.
            IF OBJECT_ID ('tempdb..##ColumnsByValue') IS NOT NULL 
                BEGIN 
                    DROP TABLE ##ColumnsByValue 
                END

            -- Create a new temp table
            CREATE TABLE ##ColumnsByValue (
                K nvarchar(255), -- Key
                N nvarchar(255), -- Column Name
                V nvarchar(255)  -- Column Value
            )

            -- Populate it with the results from our dynamically generated SQL.
            INSERT INTO ##ColumnsByValue EXEC @dbContext @SQLUnion;
        END
END
GO
SP将多个输入作为参数,这些在以下代码中解释

请注意,我还提供了一种机制来添加忽略列表作为输入:

这允许您列出任何不应包含的列名 在结果中。 不需要添加用作键的columnn,即示例结构中的行id。 您必须包括其他非varchar列 这些将导致错误,因为SP只是执行varchar比较 在它查看的所有列上。 这是通过必须创建/填充的临时表完成的 您的示例表结构表明 该表只包含感兴趣的列,因此这可能不适用于 你 我提供了如何执行此操作的示例代码,但仅在需要时执行此操作:

现在,要启动构建temp结果表的过程,请使用以下代码并根据需要进行修改

-- Build the ##ColumnsByValue table
EXEC dbo.GetColumnsByValue
    @idColumn = 'row_id',   -- The name of the column that contains your row ID (eg probably your PK column)
    @dbName = 'your_db_name',
    @tableName = 'your_table_name',
    @schemaName = 'dbo',
    @debugMode = 0          -- Set this to 1 if you just want a print out of the SQL used to build the temp table, to 0 if you want the temp table populated
这将为您留下ColumnsByValue,您可以在其上执行所需的任何搜索,例如:

select * from ##ColumnsByValue WHERE v = 'luxury' and k = 5 --some_row_id
您需要重新执行存储过程,如果相关的话,为要检查的每个表在它之前创建/修改ignore list表

这种方法的一个问题是,在您的情况下,nvarchar长度可能会超过。你会怀疑的。需要使用不同的数据类型,减少列名长度等,或者将其分解为子步骤,并将结果合并在一起,以获得所需的结果集


我担心的另一个问题是,对于您的特定场景来说,这完全是过火了。在这个场景中,一个一次性的脚本查询窗口将为您提供所需的基础,然后在eg Notepad++中进行一些巧妙的文本编辑将使您一路实现。。。因此,这个问题很可能也很合理地推迟你这样做!但这是一个很好的一般案例问题,因此对未来感兴趣的人都应该得到答案;-

是的,我已经从系统表中看到了使用meta来实现这一点,我相信比我更熟悉的人会提供这些方面的答案。但同时,请尝试右键单击“表>脚本表为>创建到>新建查询编辑器”窗口?脚本中给出了整个列列表。复制它并根据需要使用字段。自从没有人提出基于元的答案以来。。。我在下面添加了一个在小型测试db.Sepster上对我有用的测试,我尝试了你的查询。我不确定我是否做对了。我设置@dbName='my database name',schemaName='dbo'和tName='dbo.my table name'。查询已成功执行,但未发生任何事件。您的查询是否对我的表进行了永久性更改,还是只是临时更改?代码将运行并返回您提到的结果。如何在select语句中使用您的代码。我试着运行SELECT Column_Name,其中Column_Value='luxury';执行此查询后,出现错误。代码正常,但结果仅为“command completed successfully”。它没有给我一个结果集。我现在该怎么办?@sequel.learner我已经完全更新了代码,所以我认为它更方便用户。有一个通读和运行它,如果它是有意义的。你能删除你的上述评论,以获得一个干净的记录,然后把你可能对此有任何进一步的问题作为新的评论发表吗?
-- Build the ##ColumnsByValue table
EXEC dbo.GetColumnsByValue
    @idColumn = 'row_id',   -- The name of the column that contains your row ID (eg probably your PK column)
    @dbName = 'your_db_name',
    @tableName = 'your_table_name',
    @schemaName = 'dbo',
    @debugMode = 0          -- Set this to 1 if you just want a print out of the SQL used to build the temp table, to 0 if you want the temp table populated
select * from ##ColumnsByValue WHERE v = 'luxury' and k = 5 --some_row_id