0

ユーザーが現在表示しているテーブルと提供されている検索用語に基づいてSQLデータベースを検索できる、作成中のJavaアプリの検索を作成する必要があります。最初は、次のような簡単なことをするつもりでした。

SELECT * FROM <table name> WHERE CAST((SELECT COLUMN_NAME 
  FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '<table name>') 
  AS VARCHAR) LIKE '%<search term>%'

しかし、そのサブクエリは複数の結果を返すので、次のように、特定のテーブルのすべての列をループして、関連するフィールドを結果テーブルに配置するプロシージャを作成しようとしました。

CREATE PROC sp_search
    @tblname VARCHAR(4000),
    @term VARCHAR(4000)
AS
    SET nocount on
    SELECT COLUMN_NAME 
    INTO #tempcolumns
    FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = @tblname

    ALTER TABLE #tempcolumns
    ADD printed BIT,
        num SMALLINT IDENTITY

    UPDATE #tempcolumns
        SET printed = 0

    DECLARE @colname VARCHAR(4000),
        @num SMALLINT
    WHILE EXISTS(SELECT MIN(num) FROM #tempcolumns WHERE printed = 0)
    BEGIN
        SELECT @num = MIN(num) 
            FROM #tempcolumns 
            WHERE printed = 0
        SELECT @colname = COLUMN_NAME 
            FROM #tempcolumns 
            WHERE num = @num
        SELECT * INTO #results FROM @tblname WHERE CAST(@colname AS VARCHAR) 
                    LIKE '%' + @term + '%' --this is where I'm having trouble
        UPDATE #tempcolumns
            SET printed = 1
            WHERE @num = num

    END

    SELECT * FROM #results
GO

これには2つの問題があります。1つは、どういうわけか無限ループでスタックすることです。もう1つは、@tblnameから何も選択できないことです。動的SQLも使用してみましたが、それから結果を取得する方法や、それが可能かどうかさえわかりません。

これは私が大学でやっている任務のためであり、私はそれを理解しようと何時間も試みた後、これまでに得ました。私がやりたいことをする方法はありますか?

4

2 に答える 2

0
  1. テーブル内のすべての列 (整数、日付、GUID などを含む場合があります) ではなく、実際に文字列を含む列のみを検索する必要があります。
  2. #temp テーブルは必要ありません (もちろん ##temp テーブルも必要ありません)。
  3. 動的 SQL を使用する必要があります (ただし、これがこれまでのカリキュラムの一部であったかどうかはわかりません)。
  4. いくつかの簡単な規則に従うことは有益だと思いますが、あなたはそのすべてに違反しています:
    • 使用しPROCEDUREないPROCでください。これは「プロック」ではなく、「ストアド プロシージャ」です。
    • dbo.object を参照するときは (または代替スキーマ) プレフィックスを使用します。
    • プロシージャ本体をBEGIN/でラップしますEND
    • 母音を自由に使う。@tblnameまたはの代わりに言って、時間を気にせずに多くのキーストロークを節約しています@tablename@table_name? 私は特定の規則のために戦っているわけではありませんが、読みやすさを犠牲にして文字を保存することは、70 年代にその魅力を失いました。
    • sp_ストアド プロシージャにはプレフィックスを使用しないでください。このプレフィックスは、SQL Server で特別な意味を持ちます。手順に名前を付けてください。接頭辞がなくてもテーブルであることがわかっているように、接頭辞は必要ありませんtbl。そこにプレフィックスが本当に必要な場合は、usp_orのような別のものを使用しますが、proc_個人的には、プレフィックスがまだ持っていない情報を提供するとは思いません。
    • テーブルは Unicode を使用して格納されているため (一部の列もそうである可能性があります)、パラメーターはNVARCHARではなくである必要がありますVARCHAR。また、識別子は 128 文字に制限されているため、 で 257 文字を超える文字をサポートする理由はありません@tablename
    • ステートメントはセミコロンで終了します
    • 代わりにカタログ ビューを使用しINFORMATION_SCHEMAてください。
CREATE PROCEDURE dbo.SearchTable
    @tablename NVARCHAR(257),
    @term      NVARCHAR(4000)
AS
BEGIN
    SET NOCOUNT ON;

    DECLARE @sql NVARCHAR(MAX);

    SET @sql = N'SELECT * FROM ' + @tablename + ' WHERE 1 = 0'; 

    SELECT @sql = @sql + ' 
      OR ' + c.name + ' LIKE ''%' + REPLACE(@term, '''', '''''') + '%'''
    FROM 
      sys.all_columns AS c
    INNER JOIN 
      sys.types AS t
      ON c.system_type_id = t.system_type_id
      AND c.user_type_id = t.user_type_id
    WHERE 
      c.[object_id] = OBJECT_ID(@tablename)
      AND t.name IN (N'sysname', N'char', N'nchar', 
        N'varchar', N'nvarchar', N'text', N'ntext');

    PRINT @sql;

    -- EXEC sp_executesql @sql;
END
GO

目的のクエリが出力されていることに満足したらSELECT、 をコメントアウトし、 のコメントPRINTを外しEXECます。

于 2012-07-01T17:30:57.177 に答える
0

EXISTS(SELECT MIN(num) FROM #tempcolumns WHERE printed = 0)一致がない場合でも常に行を返すため、無限ループに入ります-EXISTS (SELECT * ....代わりに必要です

動的 SQL を使用するには、実行する SQL ステートメントの文字列 (varchar) を構築する必要があります。EXEC

例えば:

 declare @s varchar(max)
 select @s = 'SELECT * FROM mytable '
 Exec (@s)
于 2012-07-01T14:47:34.353 に答える