0


0

SQLスカラー値関数内のSQLコード-一般化する-最適化する

このコードを取得しました。最適化したいと思います。 基本的に、後で「Disp」テーブルに新しい列を追加できますが、この関数を変更したくありません。 動的SQLを使用できません。 右? 私の場合に機能するものは他にありますか?

これが機能です。

ALTER FUNCTION [GetDate]
(@hdrnumber INT, @DateColName VARCHAR(50))
RETURNS DATETIME
AS
BEGIN
    DECLARE @dt DATETIME
        SELECT  @dt = CASE
          WHEN @DateColName = 'ord_bookdate' THEN [ord_bookdate]
          WHEN @DateColName = 'ord_startdate' THEN [ord_startdate]
          WHEN @DateColName = 'ord_completiondate' THEN [ord_completiondate]
          WHEN @DateColName = 'pack_date_from' THEN [pack_date_from]
          WHEN @DateColName = 'pack_date_to' THEN [pack_date_to]
         END
        FROM    [Disp]
        WHERE   [hdrnumber] = @hdrnumber

    RETURN @dt
END

(長いコードなので、コードの一部を削除しましたが、ここで残したことがあなたにとって意味があることを願っています)

この機能はどのように使用しますか? 基本的には次のようになります:

 insert into tablename (...)
 select somedate, [GetDate](somedate, somecolumn)
 from sometable
 where 1 = 1

3 Answer


1


確かに、前の2つの回答で提供されたコメントに同意します。

とにかく、次の関数を記述して、特定のテーブルの列名を取得し、列名を@DatecolumNameと比較して値を返すことができます。

作成する

function [dbo].[ftTableSchema](@TableName varchar(100))  returns table as
return
--Declare @tableName varchar(30); select @TABLENAME='excelInBom'

SELECT ColumnName=Column_Name
            ,DataType= case data_type
                            When  'DECIMAL' then 'DECIMAL('+convert(varchar,Numeric_precision)+','+Convert(varchar,Numeric_scale)+')'
                            When  'NUMERIC' then 'DECIMAL('+convert(varchar,Numeric_precision)+','+Convert(varchar,Numeric_scale)+')'
                            when 'VARCHAR' then 'VARCHAR('+Convert(varchar,Character_maximum_length)+')'
                            WHEN 'CHAR' THEN  'CHAR('+Convert(varchar,Character_maximum_length)+')'
                            ELSE data_type
                          end

,ColumnOrder=Ordinal_Position,* FROM INFORMATION_SCHEMA.COLUMNS
WHERE [email protected]


0


ここでより大きな設計上の問題があると思います。 これをどのように使用していますか? 列を文字列(??!)として指定する必要がある場合、多くの重要な状況で動的SQLは>> SO <<になります。 このようなもの:

declare @sql NVARCHAR(MAX);
set @sql = 'SELECT ' + @DateColName + ' FROM disp WHERE hdrnumber = @hdrnumber';
EXEC (@sql, @hdrnumber);

(SQLが@DateColNameにSQLを挿入できないことに注意してください)。

しかし、より大きな問題は、このコード全体にあるデザインの匂いです。 この関数が存在するという事実は、あなたがどのようにそれを使うことができるかについて私を心配させます。 もっと大きく見て、デザインに関する一般的な詳細な質問をもう1つ投稿してください。さらに役立つ答えが得られると思います。


0


ユーザー定義関数内で実行できない動的SQLを使用する必要があるため(関数から削除する必要があります)、またはCASEステートメントで実行しているように(完全に汎用的ではありません) )。

私は個人的にCASEアプローチを採用して、より良いパフォーマンスを提供することが証明された場合は動的SQLを検討します(可能性のあるフィールドの数が多い場合)。 CASEを最新の状態に保つためにメンテナンス作業を行う必要がありますが、これほど頻繁にフィールドが追加されるとは思いませんか?