2017-12-04 12 views
1

을 원하는 나는이 두 기능 썼다 :SQL 기능 내가

USE muziekdatabase 
GO 
CREATE FUNCTION fnSpecNivAantal 
    (
     @Niveau as char(1) 
    ) 

RETURNS char(1) 
AS 

BEGIN 

    DECLARE @Aantal AS int 

    IF @Niveau = 'A' 
    SET @Aantal = (SELECT COUNT(*) FROM STUK WHERE niveaucode = 'A') 

    ELSE IF @Niveau = 'B' 
    SET @Aantal = (SELECT COUNT(*) FROM STUK WHERE niveaucode = 'B') 

    ELSE IF @Niveau = 'C' 
    SET @Aantal = (SELECT COUNT(*) FROM STUK WHERE niveaucode = 'C') 

RETURN @Aantal 

END 

USE muziekdatabase 
GO 

ALTER FUNCTION fnHoogsteNummer 
    (
     @EersteNummer as numeric, 
     @TweedeNummer as numeric 
    ) 
RETURNS numeric 
AS 
BEGIN 

    DECLARE @HoogsteNummer as VARCHAR(MAX) 

    IF MAX(@Eerstenummer) > MAX(@TweedeNummer) 
    SET @HoogsteNummer = @EersteNummer 
    ELSE IF 
    MAX(@Tweedenummer) > MAX(@Eerstenummer) 
    SET @HoogsteNummer = @TweedeNummer 
    ELSE IF 
    @EersteNummer = @TweedeNummer 
    SET @HoogsteNummer = 'Nummers zijn gelijk' 
    ELSE 
    SET @HoogsteNummer = 'Er is iets fout gegaan' 

    RETURN @HoogsteNummer 
END 

을 이제 그들은 그들이해야처럼 거의 작동합니다. 그러나 그다지 옳지 않은 한 가지가 있습니다. 내 함수에 값을 삽입하면 결과는 같은 대답을 가진 전체 목록이됩니다. 단지 3 행 10 행처럼 번호 3 행 1이어야합니다. 나는 DISTINCT, 사용할 수있는 알고 있지만 뭔가가 함수가 잘못 생각합니다. 나는 CASE/WHEN을 사용하려고하지만 .. 하나

+1

사용중인 dbms에 태그를 지정하십시오. (해당 코드는 제품마다 다릅니다.) – jarlh

+0

MS SQL Server 2017 – MrEmper

+0

@MrEmper. . . 코드에는 너무 많은 오류가있어서 너무 광범위하게 닫을 수 있습니다. ('SELECT'가없는'MAX() '를 사용하고, 숫자와 같은 문자열을 설정하고, 함수가 숫자를 반환 할 때 문자열을 반환하고, 더 많은 것은 의심의 여지가 없습니다). –

답변

1
CREATE FUNCTION fnSpecNivAantal 
(
@Niveau as char(1) 
) 
RETURNS INT --<-- since you are returning count use INT variable not char 
AS 
BEGIN 

    DECLARE @Aantal AS int; 

    IF (@Niveau IN ('A' , 'B', 'C')) 
    BEGIN 
     SELECT @Aantal = COUNT(*) 
     FROM STUK WHERE niveaucode = @Niveau 
    END 

RETURN @Aantal 

END 

을 작동하지 않습니다 그리고 유감이 두 번째 함수의 의미가 없습니다.

+0

고마워요!훨씬 더 좋아 보일지라도 여전히 동일한 결과를 제공합니다. https://i.imgur.com/XKMtrgI.png – MrEmper

+0

함수는 테이블의 각 행에 대해 실행됩니다. 간단한 카운트를 원하면 함수를 사용하지 말고'SELECT * '를 사용해서는 안됩니다. –

+0

나의 영웅, 이것이 해결책입니다! 의견을 보내 주신 모든 분들께 감사 드리며 올바른 답을 찾기 위해 노력했으며,이 포럼을 사용해야하는 방식을 많이 배웠습니다! – MrEmper

0

이러한 기능을 인라인 테이블 값 함수로 변경하면 성능상의 이점이 있습니다. 기능에 대해서는 생각하지만 노력할만한 가치가있는 약간 다른 방식입니다. 변수 및 매개 변수의 크기와 정밀도를 정의하는 것이 습관입니다. 게으르지 말고 숫자와 같은 일을하지 마십시오. 당신은 정확해야하며 크기를 정의해야합니다. SQL Server는 발견 한 값에 맞게 자동으로 배율 및 정밀도를 조정하지 않습니다. 반대로 귀하의 데이터에 적합하거나 그렇지 않을 수있는 기본 크기를 사용합니다.

첫 번째 기능은 이렇게 간단하게 표현할 수 있습니다.

CREATE FUNCTION fnSpecNivAantal 
(
    @Niveau as char(1) 
)RETURNS TABLE AS RETURN 

    SELECT Niveau = COUNT(*) 
    FROM STUK 
    WHERE niveaucode = @Niveau 
     AND niveaucode IN ('A', 'B', 'C') 

두 번째는 조금 다릅니다. 함수를 숫자 (배율 또는 정밀도 없음)를 반환하는 것으로 정의했지만 코드에서 숫자 또는 문자열 리터럴을 반환 할 수 있습니다. 이것은 함수의 모든 부분이 동일한 데이터 유형을 반환해야하기 때문에 작동하지 않습니다. 거대한 거래가 아니라 반환 데이터 유형이 숫자가 아니라 여기에 varchar임을 인식해야합니다. 이 함수는 이와 같이 인라인 테이블 값 함수로 변환 될 수 있습니다.

ALTER FUNCTION fnHoogsteNummer 
    (
     @EersteNummer as numeric, --need to define scale and precision 
     @TweedeNummer as numeric --need to define scale and precision 
    ) 
RETURNS TABLE AS RETURN 

    SELECT CASE WHEN @Eerstenummer > @TweedeNummer THEN convert(varchar(25), @EersteNummer) 
      WHEN @TweedeNummer > @EersteNummer THEN convert(varchar(25), @TweedeNummer) 
      WHEN @TweedeNummer = @EersteNummer THEN 'Nummers zijn gelijk' 
      ELSE 'Er is iets fout gegaan' 
      END 

이 두 기능은 모두 단일 성명입니다. 이것이 인라인 테이블 값 함수가되는 이유입니다. 변수 정의를 시작하고 다중 명령문을 사용하면 다중 명령문 테이블 값 함수가되고 성능은 스칼라 함수보다 더 나쁠 수 있습니다.

+0

이것은 완벽합니다. 감사합니다! – MrEmper