Ответ 1
Попробуйте оператор if...
if @value is null
insert into t (value) values (default)
else
insert into t (value) values (@value)
У меня есть таблица со столбцом со значением по умолчанию:
create table t (
value varchar(50) default ('something')
)
Я использую хранимую процедуру для вставки значений в эту таблицу:
create procedure t_insert (
@value varchar(50) = null
)
as
insert into t (value) values (@value)
Вопрос в том, как заставить его использовать значение по умолчанию, если @value
is null
? Я пробовал:
insert into t (value) values ( isnull(@value, default) )
Это явно не сработало. Также попробовал оператор case
, но это тоже не очень хорошо. Любые другие предложения? Я иду об этом неправильно?
Обновление: я пытаюсь выполнить без:
default
в нескольких местах и insert
.Если это невозможно, я думаю, мне просто нужно жить с ним. Кажется, что-то это должно быть достижимо.
Примечание: моя фактическая таблица имеет более одного столбца. Я просто быстро написал пример.
Попробуйте оператор if...
if @value is null
insert into t (value) values (default)
else
insert into t (value) values (@value)
Кристоф,
Значение по умолчанию для столбца применяется только в том случае, если вы не укажете столбец в инструкции INSERT.
Так как вы явно перечисляете столбец в своем заявлении insert, а параметр explicity - 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, который динамически создает и выполняет инструкцию insert в соответствии с параметрами ввода
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 для соответствующих столбцов, но, честно говоря, я мог бы просто добавить значение по умолчанию к параметру в верхней части процедуры.
Насколько мне известно, значение по умолчанию вводится только тогда, когда вы не указываете значение в инструкции insert. Так, например, вам нужно сделать что-то вроде следующего в таблице с тремя полями (значение 2 по умолчанию)
INSERT INTO t (value1, value3) VALUES ('value1', 'value3')
И тогда значение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') )
Это лучшее, что я могу придумать. Это предотвращает внедрение SQL-запросов только одним инструктором insert и может быть расширено с помощью дополнительных операторов 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
chrisofspades,
Насколько я знаю, это поведение несовместимо с тем, как работает движок db, но есть простое (я не знаю, элегантно ли, но результативно) решение для достижения двух целей НЕ НЕ
Решение состоит в том, чтобы использовать два поля: одно значение, равное нулю, для вставки, а другое - для выбора:
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)**)
Надеюсь, это поможет.
Вы можете использовать значения по умолчанию для параметров хранимых процедур:
CREATE PROCEDURE MyTestProcedure ( @MyParam1 INT,
@MyParam2 VARCHAR(20) = ‘ABC’,
@MyParam3 INT = NULL)
AS
BEGIN
-- Procedure body here
END
Если @MyParam2 не указан, он будет иметь значение "ABC"...
Не указывать столбец или значение при вставке, а значение константы DEFAULT будет заменено отсутствующим значением.
Я не знаю, как это будет работать в одной таблице столбцов. Я имею в виду: это было бы, но это было бы не очень полезно.
Вы можете использовать функцию COALESCE в MS SQL.
INSERT INTO t (значение) ЦЕННОСТИ (COALESCE (@value, 'something'))
Лично я не сумасшедший об этом решении, поскольку это кошмар обслуживания, если вы хотите изменить значение по умолчанию.
Мое предпочтение было бы предложением Mitchel Sellers, но это не работает в MS SQL. Невозможно говорить с другими SQL-dbms.
Надеюсь, что помог -newbie, как я есть, кто использует утверждения Upsert в MSSQL.. (Этот код, который я использовал в своем проекте на MSSQL 2008 R2, и работает просто идеально. Может быть, это не лучшая практика.. Время выполнения статистика показывает время выполнения как 15 миллисекунд с инструкцией insert)
Просто установите поле столбца "Значение по умолчанию или привязка" как то, что вы решите использовать как значение по умолчанию для своего столбца, а также установите столбец как "Не принимать нулевые значения из меню дизайна" и создайте этот сохраненный файл 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 - это столбец фотографий, который хранится в виде массива байтов. - И я планировал использовать фотографию по умолчанию, когда фотографии нет. --to 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`
С достаточным значением по умолчанию для таблицы вы можете просто сказать:
INSERT t DEFAULT VALUES
Обратите внимание, что это довольно маловероятный случай.
Мне нужно было использовать его только один раз в рабочей среде. У нас было две тесно связанные таблицы, и нам нужно было гарантировать, что ни одна таблица не имеет того же UniqueID, поэтому у нас была отдельная таблица, в которой был только столбец идентификаторов, и лучший способ вставить в нее был с синтаксисом выше.
Самое сжатое решение, которое я мог бы придумать, - это следить за вставкой с обновлением для столбца со значением по умолчанию:
IF OBJECT_ID('tempdb..#mytest') IS NOT NULL DROP TABLE #mytest
CREATE TABLE #mytest(f1 INT DEFAULT(1), f2 INT)
INSERT INTO #mytest(f1,f2) VALUES (NULL,2)
INSERT INTO #mytest(f1,f2) VALUES (3,3)
UPDATE #mytest SET f1 = DEFAULT WHERE f1 IS NULL
SELECT * FROM #mytest
Лучшим вариантом является создание триггера 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
Это заставляет работать NO MATTER, какой код пытается вставить NULL в вашу таблицу, избегает хранимых процедур, полностью прозрачен, и вам нужно только поддерживать значения по умолчанию в одном месте, а именно этот триггер.
Шаблон, который я обычно использую, состоит в том, чтобы создать строку без столбцов, которые имеют ограничения по умолчанию, а затем обновить столбцы, чтобы заменить значения по умолчанию предоставленными значениями (если не ноль).
Предполагая, что 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
Приветствия...
Таблица Аджунто. Процедура вставки Изъятие: проверка по умолчанию 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'
Самый простой способ сделать это - изменить объявление таблицы как
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.
Другие опубликовали правильный базовый ответ: предоставленное значение, включая нуль, является чем-то, и поэтому оно используется. Значение по умолчанию ONLY предоставляет значение, когда ни один не предоставляется. Но реальной проблемой здесь является отсутствие понимания значения null.
.