[SQL] 동적 정렬 SQL 저장 프로 시저 내에서
SQL동적 정렬 SQL 저장 프로 시저 내에서
이것은 내가 과거에 연구 시간을 보냈으니 문제입니다. 이 있었어야 뭔가 현대 RDBMS 솔루션에 의해 해결하지만, 아직 나는 정말 내가 무엇을보고 주소 데이터베이스 백엔드있는 모든 웹 또는 Windows 응용 프로그램에서 매우 일반적인 요구 될 것을 아무것도 발견하지 않은 것으로 나에게 보인다.
나는 동적 정렬의 이야기. 내 환상의 세계에서는 같은 단순하게해야한다 :
ORDER BY @sortCol1, @sortCol2
이것은 초보자 SQL에 의해 주어진 모든 인터넷을 통해 포럼을 통해 절차 개발자를 저장 정규 예이다. "왜이 가능하지?" 그들이 묻다. 변함없이, 누군가가 결국은 ORDER BY 절에 직접 매개 변수를 넣을 수없는 이유를 저장 일반적으로 실행 계획의 절차 및 기타 모든 종류의 이유의 컴파일 된 자연 현상에 대해 그들에게 강의를 함께 제공됩니다.
나는 당신 중 일부는 이미 생각하고있는 것을 알고있다. "클라이언트가 다음 정렬을하자" 당연히,이 데이터베이스에서 작업을 오프로드. 우리의 경우, 비록 우리의 데이터베이스 서버도 시간의 땀 99 %를 파괴하지 않으며 그들은 심지어 멀티 코어 아직 또는 6 개월마다 일어날 시스템 아키텍처에 다른 수많은 개선의 수 없습니다. 혼자 이런 이유로 갖는 우리의 데이터베이스는 문제가되지 않을 것이다 정렬을 처리합니다. 또한, 데이터베이스는 정렬에 아주 좋다. 그들은 그것을 위해 최적화되어 있으며, 바로 그 일에 대한 언어는 매우 유연하고 직관적이며 간단하게 얻을 수 년이 있고 무엇보다도 어떤 초보자 SQL 작가는 어떻게 편집 그것에 그것을 더욱 중요한 것은 그들이 알고하는 방법을 알고 데이터베이스가 과세되는 것을 멀리하고 방금이 당연한 선택처럼 보인다 개발 시간을 간단하게 (그리고 단축!)하고 싶은 경우 등 유지 보수를 수행, 변경합니다.
그런 다음 웹 문제가있다. 나는 HTML 테이블의 정렬 클라이언트 측을 자바 스크립트로 주위를 해본 적이 있지만, 그들은 필연적으로, 내 요구에 대한 유연한 부족하고, 다시 내 데이터베이스가 과도하게 과세되지 않기 때문에 정말 정말 쉽게 정렬 할 수있는 I 힘든 시간이 다시 쓰기 또는 롤 - 내 - 자신의 자바 스크립트 분류기에 걸리는 시간을 정당화가있다. 이미 아마 많은 자바 스크립트를 선호하고 있지만 동일은 일반적으로 서버 측 정렬을 위해 간다. 그래서 저를 고소, 특히 데이터 집합의 오버 헤드를 좋아 하나 아니에요.
오히려,하지 쉽게 또는 - 그러나 그것이 불가능하다는 점을 다시 제공합니다. 나는 이전 시스템, 동적 정렬을 얻기의 믿을 수 없을만큼 해킹 방법을, 완료했습니다. 그것은하지 꽤 않으며, 직관적 인, 간단한, 또는 유연이었고, 초보자 SQL 작가는 초 이내에 손실됩니다. 이미이 순전히 "솔루션"하지만 것으로보고있다 "합병증."
다음 예는 모범 사례 또는 좋은 코딩 스타일 또는 아무것도의 어떤 종류를 노출하는 의미도 그들이 T-SQL 프로그래머로서 내 능력을 나타내는되어 있지 않습니다. 그들은 그들이 무엇이며, 나는 완전히, 그들이 혼동 인정 나쁜 형성하고, 그냥 일반 해킹.
우리는 (그냥 "종류"매개 변수를 부르 자) 저장 프로 시저에 매개 변수로 정수 값을 전달했고, 그로부터 우리는 다른 변수의 무리를 결정한다. 예를 들어 ...의 정렬 1 (또는 기본값)입니다 가정 해 봅시다 :
DECLARE @sortCol1 AS varchar(20)
DECLARE @sortCol2 AS varchar(20)
DECLARE @dir1 AS varchar(20)
DECLARE @dir2 AS varchar(20)
DECLARE @col1 AS varchar(20)
DECLARE @col2 AS varchar(20)
SET @col1 = 'storagedatetime';
SET @col2 = 'vehicleid';
IF @sort = 1 -- Default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'asc';
SET @sortCol2 = @col2;
SET @dir2 = 'asc';
END
ELSE IF @sort = 2 -- Reversed order default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'desc';
SET @sortCol2 = @col2;
SET @dir2 = 'desc';
END
내가 정말의 값을 기준으로 정렬 할에 열 창조적 수있는 다른 열을 정의하기 위해 더 많은 @colX 변수를 선언하면 이미 방법을 볼 수 있습니다 "종류"... 그것을 사용하기 위해서는 일반적으로 다음과 같이 찾고 끝 믿을 수 없을만큼 지저분한 절 :
ORDER BY
CASE @dir1
WHEN 'desc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir1
WHEN 'asc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END,
CASE @dir2
WHEN 'desc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir2
WHEN 'asc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END
분명히 이것은 매우 벗었 예이다. 우리가 일반적으로에 정렬을 지원하기 위해 네다섯 열이 있기 때문에 실제 물건, 가능한 보조 또는 심지어 세 번째 열에 각각은 각 지원하는 양방향 (예를 들어, 날짜가 다음 내림차순 이름 오름차순에 의해 이차적으로 분류 위해) 그 외에에 정렬하려면 효과적으로 경우의 수를 두 배로 방향 정렬. 그래 ... 정말 빠른 털이 가져옵니다.
아이디어는 하나 "쉽게"등이 vehicleid가 storagedatetime 먼저 정렬됩니다 정렬 사례를 바꿀 수 있다는 것입니다 ...하지만 의사의 유연성이 간단한 예에서 적어도 정말이 끝납니다. 본질적으로, (우리의 정렬 방법은 주위에이 시간을 적용하지 않기 때문에) 테스트에 실패 각각의 경우는 NULL 값을 렌더링합니다. 그리하여 당신은 절을 결국 그 다음과 같은 기능을 수행합니다 :
ORDER BY NULL DESC, NULL, [storagedatetime] DESC, blah blah
당신은 아이디어를 얻을. SQL Server를 효과적으로 order by 절에 널 (null) 값을 무시하기 때문에 작동합니다. SQL의 기본 실무 지식을 가진 사람은 아마 볼 수 있듯이 이것은 유지 보수가 매우 어렵다. 난 당신이 중 하나를 분실 한 경우, 나쁜 생각하지 않습니다. 그것은 작업을 진행하기 위해 우리에게 오랜 시간이 걸렸습니다 그리고 우리는 여전히 편집에 노력 혼동하거나 같은 새로 만들 얻을. 다행히 그렇지 않으면이 빠르게 될 것입니다, 자주 변경이 필요하지 않습니다 "문제 가치가 없다."
그러나 그것은 일을했다.
내 질문은 다음이다 : 더 나은 방법이?
난 그냥 갈 수있는 방법이 될 수 없습니다 실현으로 나는, 저장 프로 시저 이외의 솔루션 괜찮아. 바람직하게는, 나는 누군가가 저장 프로 시저 내에서 더 잘 할 수 있는지 알고 싶습니다,하지만하지 않는 경우, 어떻게 당신이 동적으로 ASP.NET과 데이터 (양방향도)의 종류 테이블을 사용자시키는 모든 핸들을합니까?
그리고 읽기 위해 (또는 적어도 감추고에서) 같은 긴 질문 감사합니다!
추신 : 수 기뻐 내가 저장 프로 시저 ROWNUMBER를 통해 지원의 동적 정렬 것을 동적 필터링 / 텍스트 검색, 컬럼의 페이지 매김 () OVER 내 예를 보여주고, 노력하지 않았어요 ... 트랜잭션 오류에 rollbacking와 캐치를 ... "거대 규모의"도를 설명하기 시작하지 않습니다.
최신 정보:
해결법
-
==============================
1.그래, 고통, 그리고 당신이 그것을하고있는 방법은 내가 뭘 유사합니다 :
그래, 고통, 그리고 당신이 그것을하고있는 방법은 내가 뭘 유사합니다 :
order by case when @SortExpr = 'CustomerName' and @SortDir = 'ASC' then CustomerName end asc, case when @SortExpr = 'CustomerName' and @SortDir = 'DESC' then CustomerName end desc, ...
이것은 나에게 더 나은, 코드에서 동적 SQL을 구축하는 것보다 여전히있는 DBA를위한 확장 성 및 유지 보수의 악몽으로 변합니다.
내가 코드에서하는 일은 페이징 리팩토링과 나는 적어도 @SortExpr 및 @SortDir 값을 채우는 거기 반복을 많이하지 않아도 정렬.
당신이 변경을 갈 때 적어도 단정하고 인식 그래서 마찬가지로 지금까지 SQL에 관한 한, 다른 저장 프로 시저와 같은 디자인을 유지하고 서식.
-
==============================
2.이러한 접근 방식에 의해 순서대로 두 번 중복되는 것을 정렬 열을 유지하고, 좀 더 읽을 IMO입니다 :
이러한 접근 방식에 의해 순서대로 두 번 중복되는 것을 정렬 열을 유지하고, 좀 더 읽을 IMO입니다 :
SELECT s.* FROM (SELECT CASE @SortCol1 WHEN 'Foo' THEN t.Foo WHEN 'Bar' THEN t.Bar ELSE null END as SortCol1, CASE @SortCol2 WHEN 'Foo' THEN t.Foo WHEN 'Bar' THEN t.Bar ELSE null END as SortCol2, t.* FROM MyTable t) as s ORDER BY CASE WHEN @dir1 = 'ASC' THEN SortCol1 END ASC, CASE WHEN @dir1 = 'DESC' THEN SortCol1 END DESC, CASE WHEN @dir2 = 'ASC' THEN SortCol2 END ASC, CASE WHEN @dir2 = 'DESC' THEN SortCol2 END DESC
-
==============================
3.동적 SQL은 여전히 옵션입니다. 당신은이 옵션을 사용하면 현재 가지고있는 것보다 더 맛이 있는지 여부를 결정해야합니다.
동적 SQL은 여전히 옵션입니다. 당신은이 옵션을 사용하면 현재 가지고있는 것보다 더 맛이 있는지 여부를 결정해야합니다.
여기에 기사가 보이는지 : http://www.4guysfromrolla.com/webtech/010704-1.shtml.
-
==============================
4.내 응용 프로그램이 많이 할하지만 그들은 모든 동적 SQL을 구축하고있다. 그러나, 나는이 저장 프로 시저를 처리 할 때 나는이 작업을 수행 :
내 응용 프로그램이 많이 할하지만 그들은 모든 동적 SQL을 구축하고있다. 그러나, 나는이 저장 프로 시저를 처리 할 때 나는이 작업을 수행 :
그리고 적어도 동적 부분은 응용 프로그램에서,하지만 데이터베이스는 여전히 무거운 리프팅을하고있다.
-
==============================
5.나는 특정 작업에 대한 회피 동적 SQL을 사용했습니다 저장 프로 기술은 (해킹?) 고유 정렬 열을하는 것입니다. 즉,
나는 특정 작업에 대한 회피 동적 SQL을 사용했습니다 저장 프로 기술은 (해킹?) 고유 정렬 열을하는 것입니다. 즉,
SELECT name_last, name_first, CASE @sortCol WHEN 'name_last' THEN [name_last] ELSE 0 END as mySort FROM table ORDER BY mySort
이것은 하나의 제출로 이길 쉬운 - 당신은 수학 또는 날짜 기능 등으로 순서를 반대로, 당신의 mySort 열에서 필드를 CONCAT 수 있습니다
바람직하지만, 내가 사용하는 내 asp.net있는 GridViews 또는 빌드 - SQL-서버 오가는 데이터를 검색 한 후 저를 위해 정렬을 할 수 정렬과 다른 개체. 아니면 내장에없는 경우에도 - 예를 들어, datatables 등 asp.net에서.
-
==============================
6.당신이 해킹 수있는 다른 몇 가지 방법이있다.
당신이 해킹 수있는 다른 몇 가지 방법이있다.
전제 조건 :
그런 다음 임시 테이블에 삽입 :
create table #temp ( your columns ) insert #temp exec foobar select * from #temp order by whatever
방법 2 : 자체에 연결된 서버 백업 설정, 다음이 사용 OPENQUERY에서 선택 : http://www.sommarskog.se/share_data.html#OPENQUERY
-
==============================
7.서버가 여분의 사이클을 많이 가지고 있기 때문에, 세 번째 옵션이있을 수 있습니다 - 임시 테이블을 통해 정렬을 수행하는 도우미 절차를 사용합니다. 같은 뭔가
서버가 여분의 사이클을 많이 가지고 있기 때문에, 세 번째 옵션이있을 수 있습니다 - 임시 테이블을 통해 정렬을 수행하는 도우미 절차를 사용합니다. 같은 뭔가
create procedure uspCallAndSort ( @sql varchar(2048), --exec dbo.uspSomeProcedure arg1,'arg2',etc. @sortClause varchar(512) --comma-delimited field list ) AS insert into #tmp EXEC(@sql) declare @msql varchar(3000) set @msql = 'select * from #tmp order by ' + @sortClause EXEC(@msql) drop table #tmp GO
주의 :이 테스트를하지 않은,하지만 SQL Server의 작업은 2005 (사전에 열을 지정하지 않고 결과 세트에서 임시 테이블을 만들 것이다.) "해야"
-
==============================
8.어떤 시점에서, 그것은 가치가 저장 프로 시저에서 벗어나 단지 해커의 종류를 피하기 위해 매개 변수화 된 쿼리를 사용하는이되지 않습니다?
어떤 시점에서, 그것은 가치가 저장 프로 시저에서 벗어나 단지 해커의 종류를 피하기 위해 매개 변수화 된 쿼리를 사용하는이되지 않습니다?
-
==============================
9.내가 사용하는 클라이언트 측을 동의합니다. 하지만 그건 당신이 듣고 싶은 대답하지 않습니다 나타납니다.
내가 사용하는 클라이언트 측을 동의합니다. 하지만 그건 당신이 듣고 싶은 대답하지 않습니다 나타납니다.
그래서, 이건 완벽한 방법입니다. 당신이 그것을 변경하거나 심지어 물어보고 싶은 이유를 모르겠다 "더 나은 방법이 있나요." 정말,이 "길"이라고한다. 게다가, 그것은 작동하는 것 같다과 잘 프로젝트의 요구에 맞게 그리고 아마도 앞으로 수년 동안 확장 충분합니다. 데이터베이스가 과세 및 정렬은 정말하지 않기 때문에 쉽지는 앞으로 수년 동안 그 상태를 유지해야한다.
나는 그것을 걱정하지 것이다.
-
==============================
10.당신이 분류 결과를 페이징하는 경우, 동적 SQL은 좋은 옵션입니다. 당신이 열 번호 대신 열 이름을 사용할 수있는 SQL 인젝션에 대해있는 거 편집증합니다. 나는 하강 마이너스 값을 사용하기 전에이 작업을 완료했습니다. 이 같은...
당신이 분류 결과를 페이징하는 경우, 동적 SQL은 좋은 옵션입니다. 당신이 열 번호 대신 열 이름을 사용할 수있는 SQL 인젝션에 대해있는 거 편집증합니다. 나는 하강 마이너스 값을 사용하기 전에이 작업을 완료했습니다. 이 같은...
declare @o int; set @o = -1; declare @sql nvarchar(2000); set @sql = N'select * from table order by ' + cast(abs(@o) as varchar) + case when @o < 0 then ' desc' else ' asc' end + ';' exec sp_executesql @sql
그럼 그냥 확인 번호가 열 # 1 안에 확인해야합니다. 당신은 열 번호의 목록이 확장과 같은 기능을 사용하여 INT의 테이블에 그 구문을 분석 할 수있다. 그런 다음과 같이 ORDER BY 절을 구축 할 것입니다 ...
declare @cols varchar(100); set @cols = '1 -2 3 6'; declare @order_by varchar(200) select @order_by = isnull(@order_by + ', ', '') + cast(abs(number) as varchar) + case when number < 0 then ' desc' else '' end from dbo.iter_intlist_to_tbl(@cols) order by listpos print @order_by
한 가지 단점은 클라이언트 측에서 각 컬럼의 순서를 기억해야합니다. 특히, 때 모든 열을 표시하지 않거나 다른 순서로 표시합니다. 클라이언트가 정렬하고자 할 때, 당신은 열 순서로 열 이름을 매핑하고 int 치의 목록을 생성합니다.
-
==============================
11.클라이언트 측에서 정렬을 수행에 대한 인수는 대용량 데이터 및 페이지 매김입니다. 당신의 행 개수는 것 이상 얻으면 당신은 쉽게 당신은 자주 당신은 아마 SQL에서 실행하려는 스킵 / 테이크의 일환으로 정렬하고 표시 할 수 있습니다.
클라이언트 측에서 정렬을 수행에 대한 인수는 대용량 데이터 및 페이지 매김입니다. 당신의 행 개수는 것 이상 얻으면 당신은 쉽게 당신은 자주 당신은 아마 SQL에서 실행하려는 스킵 / 테이크의 일환으로 정렬하고 표시 할 수 있습니다.
엔티티 프레임 워크를 들어, 텍스트 검색을 처리하기 위해 저장 프로 시저를 사용할 수 있습니다. 같은 종류의 문제가 발생하는 경우, 내가 본 솔루션은 경기 만에 id 키 세트를 돌려 검색에 대한 저장된 프로 시저를 사용하는 것입니다. 목록 (포함)의 ID를 사용하여 DB에 대한 다음, (정렬과 함께) 다시 쿼리. EF는 ID 세트가 매우 큰 경우에도 꽤 잘 처리합니다. 예,이 두 왕복이지만, 당신은 항상 어떤 상황에서 중요 할 수있는 DB, 당신의 정렬을 유지 할 수 있고, 저장 프로 시저 로직의 적재량을 쓰는 방지를.
-
==============================
12.어떻게 결과를 표시하는 물건에 정렬 처리에 대한 - 대신 SQL보다 등 그리드, 보고서를?
어떻게 결과를 표시하는 물건에 정렬 처리에 대한 - 대신 SQL보다 등 그리드, 보고서를?
편집하다:
이 답변이 가지고 있기 때문에 일을 명확히하기 위해 다운 투표 이전에, 나는 조금 정교한거야 ...
당신은 당신이 클라이언트 측 정렬에 대해 알고 있지만, 놀지 싶었다 말했다. 그건 물론 전화,입니다.
내가 지적하고 싶은 것은, 그러나, ONCE 다음 작업 그것으로 클라이언트 측에 그것을 수행하여, 당신이있는 거 수 풀에 데이터가 그러나 당신이 원하는 것입니다 - 여러 여행을하는 대 등 서버마다에 백업하고 정렬이 변경됩니다.
귀하의 SQL 서버는 현재 과세 점점되지 않고, 그 끝내. 그것은 안된다. 그러나 아직 과부하되지해서 그것이 영원히 머물 것이다 것을 의미하지 않는다.
당신이 웹에 표시하기위한 새로운 ASP.NET 물건 중 하나를 사용하는 경우, 그 물건을 많이 이미 오른쪽 구워진다.
그것은 가치가 단지 정렬 처리하기 위해 각 저장 프로 시저에 너무 많은 코드를 추가 있습니까? 다시 전화.
나는 궁극적으로 지원 담당 할 사람이 아니에요. 그러나 열이 추가 될 때 (경우 문에 대한 수정을 요구하는) 저장 프로 시저에 의해 사용되는 다양한 데이터 세트에서 제거 / 참여 또는 갑자기 대신 두 개의 열로 정렬의 사용자가 결정할 때이 세 가지가 필요합니다 무엇을 어떤 생각을 - 당신을 필요로하는 것은 지금이 방법을 사용하여 저장 프로 시저의 모든 하나를 업데이트합니다.
나를 위해, 그것의 가치는 작동하는 클라이언트 측 솔루션을 얻을 수 및 데이터의 사용자에 직면 디스플레이의 소수에 적용과 함께 할 수. 새로운 열이 추가되면, 그것은 이미 처리합니다. 사용자가 여러 열을 기준으로 정렬하고 싶은 경우, 일종의 두 개 또는 그 스물에 의해 수 있습니다.
-
==============================
13.죄송합니다 나는 파티에 늦었어요, 그러나 여기에서 정말 동적 SQL을 피하고자하는 사람들을위한 또 다른 옵션들,하지만이 제공하는 유연성을 원하는 :
죄송합니다 나는 파티에 늦었어요, 그러나 여기에서 정말 동적 SQL을 피하고자하는 사람들을위한 또 다른 옵션들,하지만이 제공하는 유연성을 원하는 :
대신 동적으로 즉석에서 SQL을 생성, 쓰기 코드는 가능한 모든 변화에 대한 고유 시저를 생성합니다. 그런 다음 검색 옵션을보고 코드의 메소드를 작성하고 호출에 대한 적절한 PROC를 선택할 수 있습니다.
당신은 단지 몇 가지 변화가 있다면 당신은 단지 손으로 발동을 만들 수 있습니다. 당신이 다음 대신 그들 모두를 유지해야하는 변화의 많은 경우, 당신은 그냥 다시 작성해야하는 대신 PROC 생성기를 유지하는 것입니다.
추가 혜택으로, 당신도 이런 식으로 일을 더 나은 성능을 위해 더 나은 SQL 계획을 얻을 수 있습니다.
-
==============================
14.이 솔루션은 .NET의 작품은 나도 몰라 수도 있습니다.
이 솔루션은 .NET의 작품은 나도 몰라 수도 있습니다.
나는 BY 절 SQL 순서의 초기 정렬 순서는 C #에 데이터를 페치 DataView를 해당 데이터를 넣어, 세션 변수에 캐시를, 그리고 페이지를 구축하는 데 사용합니다.
때 종류 (또는 페이지, 또는 필터)에 열 머리글에 사용자가 클릭, 나는 데이터베이스에 돌아 가지 않는다. 대신에, 난 그냥 동적 SQL을 것처럼, 다시 내 캐시 DataView를에 가서 내가 동적으로 구축하는 식으로 자사의 '정렬'속성을 설정합니다. (나는 "의 RowFilter"속성을 사용하여 필터링 같은 방법을).
당신은 http://ifdefined.com/btnet/bugs.aspx에서 내 애플 리케이션, BugTracker.NET의 데모에서 일하는 기분이 / 볼 수 있습니다
-
==============================
15.당신이하지 않는 한 필요한 경우, 정렬 SQL Server를 피해야한다. 왜 종류의 애플리케이션 서버 또는 클라이언트 측에서? 또한 .NET 제네릭 뛰어난 sortin을한다
당신이하지 않는 한 필요한 경우, 정렬 SQL Server를 피해야한다. 왜 종류의 애플리케이션 서버 또는 클라이언트 측에서? 또한 .NET 제네릭 뛰어난 sortin을한다
from https://stackoverflow.com/questions/149380/dynamic-sorting-within-sql-stored-procedures by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 기본 키를 사용하여 이메일 주소? (0) | 2020.04.17 |
---|---|
[SQL] 2008 SQL 서버를 사용하는 경우 조건이 어떻게 여러 CASE해야합니까? (0) | 2020.04.17 |
[SQL] RANK ()와 DENSE_RANK () 오라클 함수의 차이점은 무엇입니까? (0) | 2020.04.17 |
[SQL] 포스트 그레스에서 재설정 자동 증가 카운터 (0) | 2020.04.17 |
[SQL] 방법에 2008 SQL Server를 사용하여 해제 IDENTITY_INSERT를 켭니다? (0) | 2020.04.17 |