2012-07-01 3 views
0

자바 응용 프로그램에 대한 검색을 만들어야합니다. 사용자가 현재보고있는 테이블과 제공하는 검색어를 기반으로 SQL 데이터베이스를 검색 할 수 있습니다. 나는 주어진 테이블의 모든 컬럼을 통해 루프 절차를 확인하고 모든 관련을 넣어 시도 그럼,주어진 테이블에 대한 동적 검색 열

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 

이 두 가지 문제가있다 : 첫째가 어떻게 든 무한 루프에 걸리면, 둘째 내가 @tblname에서 아무것도 선택하지 수 있다는 것입니다. 동적 SQL을 사용해 보았지만 그 결과를 얻는 방법이나 그것이 가능할 지 모르겠다.

이것은 내가 대학에서하는 임무를위한 것으로,이를 이해하려고 시도한이 시간이 지났습니다. 내가하고 싶은 일을 할 수있는 방법이 있습니까?

+0

제쳐두고, 길이를 지정하지 않고'VARCHAR'라고 말하지 마십시오. http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/09/bad-habits-to-kick-declaring-varchar-without-length.aspx –

+0

이전에 크기가 선언 된 위치에서 해당 문제가 발생했습니다. 1,하지만 지금은 쓸모없는 코드로 고정했습니다. 아무도 그 함정에 빠지게하지 마라. – Logan

답변

0
  1. 일반적으로 테이블의 모든 열 (정수, 날짜, GUID 등을 포함 할 수 있음)이 아닌 문자열을 포함합니다.
  2. #temp 테이블 (물론 ## temp 테이블이 아님)이 필요 없습니다.
  3. 동적 SQL을 사용해야합니다 (지금까지 커리큘럼에 포함되어 있는지 확실하지 않지만).
  4. 난 당신을 위반 한 모두, 그것은 도움이 follow a few simple conventions에 찾을 :
    • 사용 PROCEDURE하지 PROC - 그것은 "prock,"그것은이다 아니다 "저장 프로 시저가."
    • use dbo. (or alternate schema) prefix when referencing any object.
    • 절차 본문을 BEGIN/END으로 묶으십시오.
    • 모음을 자유롭게 사용하십시오. 그 많은 키 입력을 저장 하시겠습니까? @tablename 또는 @table_name 대신 @tblname으로 시간을 신경 쓰지 마십시오. 나는 특정한 대회를 위해 싸우는 것이 아니지만 가독성을 희생시키면서 문자를 저장하는 것은 70 년대에 그 매력을 잃어 버렸다.
    • 저장 프로 시저에 접두사 sp_을 사용하지 마십시오.이 접두사는 SQL Server에서 특별한 의미가 있습니다. 그것이 무엇을위한 프로 시저의 이름을 지정하십시오. 접두어가 필요하지 않습니다. 마치 접두사가 tbl이 아니더라도 테이블임을 알고있는 것처럼 말입니다. 거기에 접두어가 필요하면 usp_ 또는 proc_과 같은 다른 접미사를 사용하십시오. 그러나 개인적으로 접두사가 당신에게 아직 가지고 있지 않은 정보를 제공한다고 생각하지 않습니다.
    • 유니 코드를 사용하여 테이블을 저장하므로 (일부 열 수도 있음) 매개 변수는 NVARCHAR이어야하며 VARCHAR이 아니어야합니다. 식별자는 128 자로 제한되어 있으므로 @tablename에 257자를 넘길 이유가 없습니다.
    • terminate statements with semi-colons.
    • use the catalog views instead of 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의 주석.

+0

와우, 도움이됩니다. 내 SQL 과정은 깊이가 아니었지만 훌륭한 정보를 주셨습니다. 우리는 내가하려고하는 일을하도록 가르쳐주지 않았기 때문에 Google은이 모든 것에 대한 나의 근원이었습니다. 방금 다른 임시 테이블을 사용하여 주어진 테이블의 모든 열을 포함하는 테이블 변수를 만들려고했지만 나는 비참하게 실패했습니다. 나는 당신의 코드를 주사 할 것이다. 편집 : 그것은 완벽하게 처음으로 일했습니다. 정말 고마워! 이 문서에 대한 링크를 제 설명서에 넣을 것입니다. – Logan

0

에는 일치가없는 경우에도 EXISTS(SELECT MIN(num) FROM #tempcolumns WHERE printed = 0) 항상 행을 반환하기 때문에 당신은 무한 루프에 들어가 - 대신

동적 SQL을, 당신은 문자열 (VARCHAR)를 구축 할 필요가 사용 EXISTS (SELECT * .... 필요 실행할 SQL 문에, 당신은 EXEC

로 전화를 예를 들면 : 당신은 행동 만 검색 컬럼에 필요

declare @s varchar(max) 
select @s = 'SELECT * FROM mytable ' 
Exec (@s) 
+0

왜 무한 루프가 발생했는지 지적 해 주셔서 고쳐 주셨습니다. 동적 인 SQL에 관해서는, 내가 작전에서 말했듯이, 나는 전에 그것을 시도했다. 이제 저는 이것을 얻었습니다 : "잘못된 오브젝트 이름 '#results'." – Logan

+0

예 - @tblName 변수를 사용하여 해당 명령을 실행하기위한 문자열을 작성해야합니다. 예 : exec ('select * from'+ @tblName) – podiluska

+0

나는 이미 그렇게했으며, @tblname에서 데이터를 가져 와서 #results라는 임시 테이블에 넣었습니다.이 테이블은 분명히 액세스 할 수 없습니다. 그게 내가하고 싶은 일을 할 수있을 것 같아 sp_executesql을 사용하여 찾고 있어요. 아마 나는 너를 이해하지 않을거야. – Logan

관련 문제