我有一个包含默认值的列的表:
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
声明,但这也不太公平。还有其他建议吗?我是以错误的方式解决这个问题吗?
更新:我正在尝试完成此,不必须:
default
值,insert
语句。如果这是不可能的,那么我想我只需忍受它。似乎这应该是可以实现的。
注意:我的实际表有多个列。我只是在写一个例子。
答案 0 :(得分:12)
尝试if语句......
if @value is null
insert into t (value) values (default)
else
insert into t (value) values (@value)
答案 1 :(得分:10)
仅当您未在INSERT语句中指定列时才应用列的默认值。
由于您明确列出了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,它根据输入参数
动态构建和执行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
以下两个命令应该为您提供输出所需的示例...
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
答案 2 :(得分:3)
据我所知,只有在insert语句中没有指定值时才会插入默认值。因此,例如,您需要在包含三个字段的表中执行以下操作(value2默认)
INSERT INTO t (value1, value3) VALUES ('value1', 'value3')
然后value2将被默认。也许有人会在如何为一个单一字段的表格中实现这一目标。
答案 3 :(得分:2)
chrisofspades,
据我所知,行为与数据库引擎的工作方式不兼容, 但是有一个简单的(我不知道是否优雅但高效)解决方案来实现你的两个目标不要
解决方案是使用两个字段,一个可插入用于插入,另一个用于计算选择:
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
这种方法甚至可以让您将业务默认值的管理集中在一个参数表中,放置一个ad hoc函数来执行此操作,vg更改:
selValue AS ISNULL(insValue, 'something')
的
selValue AS ISNULL(insValue, **getDef(t,1)**)
我希望这会有所帮助。
答案 4 :(得分:2)
这是我能想到的最好的。它可以防止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
答案 5 :(得分: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') )
答案 6 :(得分:1)
您可以对存储过程的参数使用默认值:
CREATE PROCEDURE MyTestProcedure ( @MyParam1 INT,
@MyParam2 VARCHAR(20) = ‘ABC’,
@MyParam3 INT = NULL)
AS
BEGIN
-- Procedure body here
END
如果未提供@ MyParam2,则它将具有'ABC'值...
答案 7 :(得分:0)
您可以在MS SQL中使用COALESCE功能。
INSERT INTO t(value)VALUES(COALESCE(@ value,'something'))
就个人而言,我并不为这个解决方案而疯狂,因为如果你想改变默认值,这是一个维护噩梦。
我的偏好是Mitchel Sellers的提议,但这在MS SQL中不起作用。无法与其他SQL dbms对话。
答案 8 :(得分:0)
希望帮助-newbie,因为我在MSSQL中使用Upsert语句。(这个代码我在MSSQL 2008 R2的项目中使用并且工作简单完美......可能不是最佳实践..执行时间统计信息显示执行时间为15毫秒(使用insert语句)
只需将列的“默认值或绑定”字段设置为您决定用作列的默认值的字段,并将列设置为“不接受设计菜单中的空值”并创建此存储过程..
`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`
答案 9 :(得分:0)
如果桌子上有足够的默认值,您可以简单地说:
INSERT t DEFAULT VALUES
但请注意,这是一个非常不可能的情况。
我只需要在生产环境中使用一次。我们有两个密切相关的表,并且需要保证两个表都没有相同的UniqueID,所以我们有一个单独的表只有一个标识列,插入其中的最好方法是使用上面的语法。
答案 10 :(得分:0)
插入时不要指定列或值,DEFAULT constaint的值将替换缺失值。
我不知道这在单个列表中如何工作。我的意思是:它会,但它不会非常有用。
答案 11 :(得分:0)
我能提出的最简洁的解决方案是使用默认值对列进行更新:
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
答案 12 :(得分:0)
到目前为止,最好的选择是为表创建一个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插入到表中,避免存储过程,完全透明,并且您只需要在一个地方维护默认值,即此触发器。
答案 13 :(得分:0)
我通常使用的模式是创建不包含具有默认约束的列的行,然后更新列以使用提供的值替换默认值(如果不为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
干杯...
答案 14 :(得分:0)
辅助表ejemplo。 检修程序 Ejemploejecución:缺省DE SPULT en el paso al SP。
SP的标记结果,最终结果得到确认。 最低要求插入和插入值(默认) 默认版本与“默认”(逗号)不同
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'
答案 15 :(得分:-2)
提问者需要了解提供的空值与null之间的区别。
其他人已经发布了正确的基本答案:提供的值(包括null)是某种东西,因此它被使用了。默认值仅在未提供时提供值。但这里真正的问题是缺乏对null值的理解。
答案 16 :(得分:-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时才有效,否则,您的存储过程必须使用不同形式的insert来触发默认值。