【问题标题】:Search all tables for multiple values在所有表中搜索多个值
【发布时间】:2018-03-05 17:05:24
【问题描述】:

下面漂亮的SP返回表和列名和值 然而,我感兴趣的是搜索多个值。 我唯一想知道的是表/列名的不同输出而不是值。

所以基本上我想知道我的值存在的所有表/列名 然后从那里我可以进行动态更新查询以重命名现有列中的这些值 () 因此,通过连接来搜索这些值可能会更好。 我也已经考虑将整个数据库堆叠在一个巨大的表中,然后我可以加入一个喜欢的表。但这有点头疼..有什么建议吗?

CREATE PROC SearchAllTables ( @SearchStr nvarchar(100) ) 作为 开始

CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630)) SET NOCOUNT ON DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) SET @TableName = '' SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') WHILE @TableName IS NOT NULL BEGIN SET @ColumnName = '' SET @TableName = ( SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName AND OBJECTPROPERTY( OBJECT_ID( QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) ), 'IsMSShipped' ) = 0 ) WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) BEGIN SET @ColumnName = ( SELECT MIN(QUOTENAME(COLUMN_NAME)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) AND TABLE_NAME = PARSENAME(@TableName, 1) AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'int', 'decimal') AND QUOTENAME(COLUMN_NAME) > @ColumnName ) IF @ColumnName IS NOT NULL BEGIN INSERT INTO #Results EXEC ( 'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) FROM ' + @TableName + ' (NOLOCK) ' + ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2 ) END END END SELECT ColumnName, ColumnValue FROM #Results END

【问题讨论】:

  • 你能用一些例子解释一下预期结果和实际结果吗
  • 这是一种有趣的方法。我想知道首先找到所有表和字段组合然后运行一次动态SQL是否会更有效。但问题是,@SearchStr 会被模式匹配吗?我在动态 SQL 中看到了 LIKE。无论哪种方式,一个建议是在搜索字符串中放置一个分隔符,然后在外部循环中遍历这些字符分隔符。

标签: sql sql-server performance stored-procedures


【解决方案1】:

这取决于您使用的 SQL Server 版本以及用于解析文本的功能。我主要使用 SQL Server 2005,所以我很有限,但是您可以解析 @SearchStr 并将值放入临时表中,然后使用它重新加入。

DECLARE @SearchStr nvarchar(100)
SET @SearchStr = N'123|456|789|ABC|DEF|GHI'

IF OBJECT_ID(N'tempdb..#SearchStrings') IS NOT NULL DROP TABLE #SearchStrings
CREATE TABLE #SearchStrings (ID INT IDENTITY, SearchString NVARCHAR(100))

WHILE @SearchStr <> ''
BEGIN
    INSERT INTO #SearchStrings (SearchString) SELECT CASE WHEN @SearchStr LIKE N'%|%' THEN LEFT(@SearchStr, CHARINDEX('|', @SearchStr) - 1) ELSE @SearchStr END

    SET @SearchStr = STUFF(@SearchStr, 1, CASE WHEN @SearchStr LIKE N'%|%' THEN CHARINDEX('|', @SearchStr) ELSE LEN(@SearchStr) END, N'')
END

SELECT * FROM #SearchStrings

或者您可以直接解析值并直接使用它们。

DECLARE @SearchStr nvarchar(100)
SET @SearchStr = N'123|456|789|ABC|DEF|GHI'

WHILE @SearchStr <> ''
BEGIN
    PRINT CASE WHEN @SearchStr LIKE N'%|%' THEN LEFT(@SearchStr, CHARINDEX('|', @SearchStr) - 1) ELSE @SearchStr END

    SET @SearchStr = STUFF(@SearchStr, 1, CASE WHEN @SearchStr LIKE N'%|%' THEN CHARINDEX('|', @SearchStr) ELSE LEN(@SearchStr) END, N'')
END

【讨论】:

    【解决方案2】:

    我想我明白了,目的是找到我的值存在的所有表,然后基于它创建多个更新语句,例如为原始值添加一个前缀,我最终按照我的建议做也就是将整个数据库填充到 2 列中并加入这些列(与循环遍历每个值的查询相比,这恰好要快得多):

    设置 ANSI_NULLS ON 去 设置 QUOTED_IDENTIFIER ON 去 改变 PROC [dbo].[SearchAllTables] ( @SearchStr nvarchar(100) ) 作为 开始

    CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630)) SET NOCOUNT ON DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110) SET @TableName = '' SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''') WHILE @TableName IS NOT NULL BEGIN SET @ColumnName = '' SET @TableName = ( SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName AND OBJECTPROPERTY( OBJECT_ID( QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) ), 'IsMSShipped' ) = 0 AND TABLE_CATALOG = 'TPV_BE_PRD' ) WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL) BEGIN SET @ColumnName = ( SELECT MIN(QUOTENAME(COLUMN_NAME)) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = PARSENAME(@TableName, 2) AND TABLE_NAME = PARSENAME(@TableName, 1) AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar') AND QUOTENAME(COLUMN_NAME) > @ColumnName ) IF @ColumnName IS NOT NULL BEGIN INSERT INTO #Results EXEC ( 'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) FROM ' + @TableName + ' (NOLOCK) ' ) END END END SELECT distinct ColumnName FROM #Results a inner join OITM b on a.ColumnValue = b."ItemCode" COLLATE SQL_Latin1_General_CP850_CI_AS END

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-21
      • 1970-01-01
      • 1970-01-01
      • 2016-10-26
      • 1970-01-01
      • 2019-03-20
      • 2021-09-18
      • 1970-01-01
      相关资源
      最近更新 更多