Вставьте значение по умолчанию, когда параметр имеет значение NULL - PullRequest
39 голосов
/ 23 октября 2008

У меня есть таблица со столбцом со значением по умолчанию:

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 операторов.

Если это невозможно, я думаю, мне просто придется с этим смириться. Просто кажется, что-то такое должно быть достижимо.

Примечание. Моя таблица содержит более одного столбца. Я просто быстро написал пример.

Ответы [ 17 ]

12 голосов
/ 23 октября 2008

Попробуйте оператор if ...

if @value is null 
    insert into t (value) values (default)
else
    insert into t (value) values (@value)
10 голосов
/ 23 октября 2008

Кристоф,

Значение по умолчанию для столбца применяется только в том случае, если столбец не указан в операторе INSERT.

Поскольку вы явно перечислили столбец в своем операторе вставки, а для explicity задали для него значение 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 для соответствующих столбцов, но, если честно, я мог бы рассмотреть вопрос о добавлении значения по умолчанию к параметру в верхней части процедуры

3 голосов
/ 23 октября 2008

Насколько я знаю, значение по умолчанию вставляется только тогда, когда вы не указываете значение в инструкции вставки. Так, например, вам нужно сделать что-то вроде следующего в таблице с тремя полями (значение по умолчанию 2)

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

И тогда значение2 будет по умолчанию. Может быть, кто-нибудь расскажет, как это сделать для таблицы с одним полем.

2 голосов
/ 24 октября 2008

Вероятно, это не самый удобный для производительности способ, но вы можете создать скалярную функцию, которая будет извлекать информацию из информационной схемы с именем таблицы и столбца, а затем вызывать ее, используя логику 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') )
2 голосов
/ 26 апреля 2012

Это лучшее, что я могу придумать. Он предотвращает внедрение SQL-кода только в одном операторе вставки и может быть расширен с помощью дополнительных операторов.

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
2 голосов
/ 31 августа 2014

chrisofspades,

Насколько я знаю, поведение не совместимо с тем, как работает механизм БД, но есть простое (я не знаю, изящное ли оно, но производительное) решение для достижения ваших двух целей: НЕ

  1. поддерживает значение по умолчанию в нескольких местах, а
  2. использовать несколько операторов вставки.

Решение состоит в том, чтобы использовать два поля: одно обнуляемое для вставки, а другое рассчитано для выбора:

CREATE TABLE t (
    insValue VARCHAR(50) NULL
    , selValue AS ISNULL(insValue, 'something')
)

DECLARE @d VARCHAR(10)
INSERT INTO t (insValue) VALUES (@d) -- null
SELECT selValue FROM t

Этот метод даже позволяет вам централизовать управление бизнес-настройками по умолчанию в таблице параметров, поместив для этого специальную функцию, изменяя vg:

selValue AS ISNULL(insValue, 'something')

для

selValue AS ISNULL(insValue, **getDef(t,1)**)

Надеюсь, это поможет.

1 голос
/ 23 октября 2008

Вы можете использовать значения по умолчанию для параметров хранимых процедур:

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

END

Если @ MyParam2 не указан, он будет иметь значение 'ABC' ...

0 голосов
/ 09 мая 2019

Таблица дополнений. Процедура вставки Ejemplo ejecución: Ver valor DEFAULT en el paso al SP.

Итоговое окончательное постановление о дефекте, окончательное указание и указание SP. Misma técnica si no se quiere usar el SP y hacer el INSERT (CAMPOS) ЦЕННОСТИ (по умолчанию) Ver default по умолчанию отличается от 'default' (con comillas)

    create Table Cliente_SeguimientoDeuda(IDRegistro int identity(1,1), Cliente int, ReferenciaReclamacion NVarChar(20) Default 'Reclamación', 
    Fecha DateTime, PersonaContactada nvarchar(30), Causa NVarChar(50), CompromisoObtenido NvarChar(50), 
    Usuario NVarChar(50), NotasReclamacion NVarChar(500),
    Primary Key (IDRegistro))


    create procedure NET_ADDReclamacion(@Cliente int, @ReferenciaReclamacion nvarchar(20)='por defecto' , 
    @Fecha datetime, @PersonaContactada nvarchar(30),@Causa nvarchar(50), @Compromiso nvarchar(50)
    , @Usuario nvarchar(50), @NotasReclamacion nvarchar(500))
    as
    set nocount on
    insert into Cliente_SeguimientoDeuda(Cliente, ReferenciaReclamacion,Fecha, PersonaContactada,Causa,CompromisoObtenido,
    Usuario, NotasReclamacion) Values (@Cliente,@ReferenciaReclamacion,@Fecha,@PersonaContactada,@Causa,@Compromiso,
    @Usuario,@NotasReclamacion)
    select @@IDENTITY

NET_ADDReclamacion 1,default,'01-01-2019','roberto','causa','compromiso','usu','notas'
0 голосов
/ 26 сентября 2018

Шаблон, который я обычно использую, состоит в том, чтобы создать строку без столбцов с ограничениями по умолчанию, а затем обновить столбцы, чтобы заменить значения по умолчанию предоставленными значениями (если не ноль).

Предполагая, что col1 является первичным ключом, а col4 и col5 имеют стандартное ограничение

-- create initial row with default values
insert table1 (col1, col2, col3)
    values (@col1, @col2, @col3)

-- update default values, if supplied
update table1
    set col4 = isnull(@col4, col4),
        col5 = isnull(@col5, col5)
    where col1 = @col1

Если вы хотите, чтобы фактические значения по умолчанию были в таблице ...

-- create initial row with default values
insert table1 (col1, col2, col3)
    values (@col1, @col2, @col3)

-- create a container to hold the values actually inserted into the table
declare @inserted table (col4 datetime, col5 varchar(50))

-- update default values, if supplied
update table1
    set col4 = isnull(@col4, col4),
        col5 = isnull(@col5, col5)
    output inserted.col4, inserted.col5 into @inserted (col4, col5)
    where col1 = @col1

-- get the values defaulted into the table (optional)
select @col4 = col4, @col5 = col5 from @inserted

Приветствия ...

0 голосов
/ 14 апреля 2017

Наилучшим вариантом на сегодняшний день является создание триггера INSTEAD OF INSERT для вашей таблицы, удаление значений по умолчанию из вашей таблицы и перемещение их в триггер.

Это будет выглядеть следующим образом:

create trigger dbo.OnInsertIntoT
ON TablenameT
INSTEAD OF INSERT
AS
insert into TablenameT
select
   IsNull(column1 ,<default_value>)
  ,IsNull(column2 ,<default_value>)
  ...
from inserted

Это заставляет его работать Неважно, какой код пытается вставить NULL в вашу таблицу, избегает хранимых процедур, является полностью прозрачным, и вам нужно только сохранить значения по умолчанию в одном месте, а именно в этом триггере.

...