46

デフォルト値の列を持つテーブルがあります。

create table t (
    value varchar(50) default ('something')
)

このテーブルに値を挿入するためにストアド プロシージャを使用しています。

create procedure t_insert (
    @value varchar(50) = null
)
as 
insert into t (value) values (@value)

問題は、次の場合にデフォルトを使用するにはどうすればよい@valueですnullか? 私は試した:

insert into t (value) values ( isnull(@value, default) )

それは明らかにうまくいきませんでした。ステートメントも試しましたcaseが、それもうまくいきませんでした。他の提案はありますか?私はこれについて間違った方法で進んでいますか?

更新:次のことをしなくてもこれを達成しようとしています:

  1. default複数の場所で値を維持し、
  2. 複数のinsertステートメントを使用します。

それが無理なら、我慢するしかないと思います。これは達成可能であるように思われます。

注: 私の実際のテーブルには複数の列があります。私はすぐに例を書いていました。

4

16 に答える 16

18

クリストフ、

列のデフォルト値は、INSERT ステートメントで列を指定しない場合にのみ適用されます。

挿入ステートメントで列を明示的にリストし、明示的にNULLに設定しているため、その列のデフォルト値をオーバーライドしています

あなたがする必要があるのは、「nullがsprocに渡された場合、その列に挿入しようとしないでください」です。

これは、動的 SQL でそれを行う方法の簡単で厄介な例です。

デフォルト値を持ついくつかの列を持つテーブルを作成します...

CREATE TABLE myTable (
    always VARCHAR(50),
    value1 VARCHAR(50) DEFAULT ('defaultcol1'),
    value2 VARCHAR(50) DEFAULT ('defaultcol2'),
    value3 VARCHAR(50) DEFAULT ('defaultcol3')
)

入力パラメーターに基づいて挿入ステートメントを動的に構築および実行する SPROC を作成します。

ALTER PROCEDURE t_insert (
    @always VARCHAR(50),
    @value1 VARCHAR(50) = NULL,
    @value2 VARCHAR(50) = NULL,
    @value3 VARCAHR(50) = NULL
)
AS 
BEGIN
DECLARE @insertpart VARCHAR(500)
DECLARE @valuepart VARCHAR(500)

SET @insertpart = 'INSERT INTO myTable ('
SET @valuepart = 'VALUES ('

    IF @value1 IS NOT NULL
    BEGIN
        SET @insertpart = @insertpart + 'value1,'
        SET @valuepart = @valuepart + '''' + @value1 + ''', '
    END

    IF @value2 IS NOT NULL
    BEGIN
        SET @insertpart = @insertpart + 'value2,'
        SET @valuepart = @valuepart + '''' + @value2 + ''', '
    END

    IF @value3 IS NOT NULL
    BEGIN
        SET @insertpart = @insertpart + 'value3,'
        SET @valuepart = @valuepart + '''' + @value3 + ''', '
    END

    SET @insertpart = @insertpart + 'always) '
    SET @valuepart = @valuepart + + '''' + @always + ''')'

--print @insertpart + @valuepart
EXEC (@insertpart + @valuepart)
END

次の 2 つのコマンドは、出力として必要なものの例を提供する必要があります...

EXEC t_insert 'alwaysvalue'
SELECT * FROM  myTable

EXEC t_insert 'alwaysvalue', 'val1'
SELECT * FROM  myTable

EXEC t_insert 'alwaysvalue', 'val1', 'val2', 'val3'
SELECT * FROM  myTable

私はこれがあなたがする必要があることをするための非常に複雑な方法であることを知っています. 関連する列の InformationSchema からデフォルト値を同じように選択することもできますが、正直なところ、プロシージャの先頭にある param にデフォルト値を追加することを検討してください。

于 2008-10-23T18:34:42.737 に答える
11

if文を試してみてください...

if @value is null 
    insert into t (value) values (default)
else
    insert into t (value) values (@value)
于 2008-10-23T18:04:24.373 に答える
4

私の知る限り、挿入ステートメントで値を指定しない場合にのみ、デフォルト値が挿入されます。したがって、たとえば、3 つのフィールドを持つテーブルで次のようなことを行う必要があります (デフォルト値は value2 です)。

INSERT INTO t (value1, value3) VALUES ('value1', 'value3')

そして、value2 がデフォルトになります。おそらく、単一のフィールドを持つテーブルでこれを達成する方法について、誰かが協力するでしょう。

于 2008-10-23T17:39:26.403 に答える
2

これは私が思いつくことができる最高のものです。SQL インジェクションが 1 つの挿入ステートメントのみを使用するのを防ぎ、より多くの case ステートメントで拡張できます。

CREATE PROCEDURE t_insert (     @value varchar(50) = null )
as
DECLARE @sQuery NVARCHAR (MAX);
SET @sQuery = N'
insert into __t (value) values ( '+
CASE WHEN @value IS NULL THEN ' default ' ELSE ' @value ' END +' );';

EXEC sp_executesql 
@stmt = @sQuery, 
@params = N'@value varchar(50)',
@value = @value;

GO
于 2012-04-25T20:03:33.630 に答える
2

おそらく最もパフォーマンスに優しい方法ではありませんが、テーブルと列の名前を使用して情報スキーマからプルするスカラー関数を作成し、前に試した isnull ロジックを使用してそれを呼び出すことができます。

    CREATE FUNCTION GetDefaultValue
    (
        @TableName VARCHAR(200),
        @ColumnName VARCHAR(200)
    )
    RETURNS VARCHAR(200)
    AS
    BEGIN
        -- you'd probably want to have different functions for different data types if
        -- you go this route
    RETURN (SELECT TOP 1 REPLACE(REPLACE(REPLACE(COLUMN_DEFAULT, '(', ''), ')', ''), '''', '') 
            FROM information_schema.columns
            WHERE table_name = @TableName AND column_name = @ColumnName)

    END
    GO

そして、次のように呼び出します。

INSERT INTO t (value) VALUES ( ISNULL(@value, SELECT dbo.GetDefaultValue('t', 'value') )
于 2008-10-23T22:34:02.800 に答える
1

ストアド プロシージャのパラメータにはデフォルト値を使用できます。

CREATE PROCEDURE MyTestProcedure ( @MyParam1 INT,
@MyParam2 VARCHAR(20) = ‘ABC’,
@MyParam3 INT = NULL)
AS
BEGIN
    -- Procedure body here

END

@MyParam2 が指定されていない場合、値は「ABC」になります...

于 2008-10-23T17:39:52.783 に答える
0

テーブルに十分なデフォルトがある場合、次のように簡単に言うことができます。

INSERT t DEFAULT VALUES

ただし、これは非常にまれなケースであることに注意してください。

実稼働環境で一度だけ使用する必要がありました。2つの密接に関連するテーブルがあり、どちらのテーブルにも同じUniqueIDがないことを保証する必要があったため、ID列を持つ別のテーブルがあり、そこに挿入する最良の方法は上記の構文を使用することでした。

于 2012-05-31T09:51:26.637 に答える
0

挿入時に列または値を指定しないでください。DEFAULT 制約の値が欠落している値に置き換えられます。

これが単一列テーブルでどのように機能するかわかりません。つまり、そうなるでしょうが、あまり役に立ちません。

于 2008-10-23T17:40:13.640 に答える
0

MSSQL で Upsert ステートメントを使用する初心者を支援することを願っています.. (このコードは、MSSQL 2008 R2 のプロジェクトで使用し、単に完璧に動作します..ベスト プラクティスではない可能性があります..実行時間の統計は実行を示します挿入ステートメントで 15 ミリ秒の時間)

列の「デフォルト値またはバインディング」フィールドを、列のデフォルト値として使用することを決定したものとして設定し、列をデザインメニューからnull値を受け入れないように設定し、この保存されたProcを作成します..

`USE [YourTable]
GO


SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE PROC [dbo].[YourTableName]

    @Value smallint,
    @Value1 bigint,
    @Value2 varchar(50),
    @Value3 varchar(20),
    @Value4 varchar(20),
    @Value5 date,
    @Value6 varchar(50),
    @Value7 tinyint,
    @Value8 tinyint,
    @Value9 varchar(20),
    @Value10 varchar(20),
    @Value11 varchar(250),
    @Value12 tinyint,
    @Value13 varbinary(max) 

-- 私のプロジェクトでは、@Value13 は、バイト配列として保存する写真列です. -- そして、渡された写真がない場合はデフォルトの写真を使用する予定でした -- sp に db に保存します..

AS
--SET NOCOUNT ON
IF @Value = 0 BEGIN
    INSERT INTO YourTableName (
        [TableColumn1],
        [TableColumn2],
        [TableColumn3],
        [TableColumn4],
        [TableColumn5],
        [TableColumn6],
        [TableColumn7],
        [TableColumn8],
        [TableColumn9],
        [TableColumn10],
        [TableColumn11],
        [TableColumn12],
        [TableColumn13]
    )
    VALUES (
        @Value1,
        @Value2,
        @Value3,
        @Value4,
        @Value5,
        @Value6,
        @Value7,
        @Value8,
        @Value9,
        @Value10,
        @Value11,
        @Value12,
        default
    )
    SELECT SCOPE_IDENTITY() As InsertedID
END
ELSE BEGIN
    UPDATE YourTableName SET 
        [TableColumn1] = @Value1,
        [TableColumn2] = @Value2,
        [TableColumn3] = @Value3,
        [TableColumn4] = @Value4,
        [TableColumn5] = @Value5,
        [TableColumn6] = @Value6,
        [TableColumn7] = @Value7,
        [TableColumn8] = @Value8,
        [TableColumn9] = @Value9,
        [TableColumn10] = @Value10,
        [TableColumn11] = @Value11,
        [TableColumn12] = @Value12,
        [TableColumn13] = @Value13
    WHERE [TableColumn] = @Value

END
GO`
于 2012-02-20T12:47:19.990 に答える
0

MS SQL で COALESCE 関数を使用できます。

INSERT INTO t (値) VALUES( COALESCE(@value, 'something') )

個人的には、デフォルト値を変更したい場合のメンテナンスの悪夢であるため、このソリューションに夢中ではありません。

私の好みは Mitchel Sellers の提案ですが、それは MS SQL では機能しません。他の SQL dbms と通信できません。

于 2008-10-23T21:32:28.367 に答える
-2

これを行う最も簡単な方法は、テーブル宣言を次のように変更することです。

CREATE TABLE Demo
(
    MyColumn VARCHAR(10) NOT NULL DEFAULT 'Me'
)

これで、ストアド プロシージャで次のようなことができます。

CREATE PROCEDURE InsertDemo
    @MyColumn VARCHAR(10) = null
AS
INSERT INTO Demo (MyColumn) VALUES(@MyColumn)

ただし、このメソッドは null を使用できない場合にのみ機能します。それ以外の場合、ストアド プロシージャは別の形式の挿入を使用してデフォルトをトリガーする必要があります。

于 2008-10-23T17:50:12.637 に答える
-4

質問者は、提供された空の値と null の違いを学ぶ必要があります。

他の人は正しい基本的な答えを投稿しています:nullを含む提供された値は何かであるため、使用されます。デフォルトは、値が指定されていない場合にのみ値を提供します。しかし、ここでの本当の問題は、null の値を理解していないことです。

.

于 2008-10-23T20:32:12.123 に答える