这个问题是关于 NULL 的正确使用和对业务逻辑与存储过程的 CHECK 约束的使用。
我有以下表格设置。

我对表进行了标准化以避免使用 NULL。问题是这些表中的一些由于业务流程而相互依赖。有些设备必须经过消毒,有些设备在另一个系统中进行跟踪。所有设备最终都将在处置表中处置。
问题是我需要执行检查,例如如果布尔字段RequiresSantization为真,则在DisposalDate输入Sanitize字段之前无法输入。
此外,如果布尔值为IsTrackedInOther真,则OfficialOutOfService必须先输入字段,然后DisposalDate才能输入。
如果我将所有这些列合并到Archive.Device表中,那么我将拥有 NULL 字段,但我将能够使用 CHECK 约束管理所有业务规则。
另一种方法是让表保持原样,并通过从表中选择以检查记录是否存在,然后抛出适当的错误来管理存储过程中的业务逻辑。
这是可以适当使用 NULL 的情况吗?布尔领域IsTrackedInOther
和RequiresSanitization基本赋予意义的NULL字段。如果IsTrackedInOther是,false则设备未在其他系统中跟踪SectionID并且SpecialDeviceCode为 NULL,我知道它们应该为 NULL,因为它未在其他系统中跟踪。同样,OfficialOutOfServiceDate和OOSLogPath我知道会是NULL藏汉,并且DisposalDate可以随时进入。
如果IsTrackedInOther是true,那么SectionID和SpecialDeviceCode将是必需的,如果OfficialOutOfServiceDate和OOSLogPath是NULL,那么我知道它们还没有被正式从该系统中删除,因此DisposalDate在输入它们之前不能有a 。
所以这是一个问题
单独的表/无 NULL/在存储过程中强制执行规则
对比
在 CHECK 约束中组合表/NULLs/强制规则。
我知道在图片中使用 NULL …
我下面的 sql 用于列出 10 天前添加的股票。Order by isnull(Price) 被使用,这样没有任何价格的股票仍然会被列出。
AddDate 和 Price 有一个索引。
SELECT Id, Price FROM tblStock
where AddDate >= date_sub(curdate(),interval 10 day)
order by isnull(Price), Price asc limit 50
Run Code Online (Sandbox Code Playgroud)
解释 sql 显示它没有使用价格指数。所以我试图改进查询并提出了以下 sql
SELECT Id, Price FROM tblStock
where AddDate >= date_sub(curdate(),interval 10 day)
and Price is not null
order by Price asc limit 50
Run Code Online (Sandbox Code Playgroud)
新的 sql 运行得更快,并且解释显示它使用价格索引,但问题是永远不会选择具有空值的价格。
寻找有关如何解决此问题的任何意见或建议。谢谢。
(SQL 和 SQL Server 相对较新)我正在阅读Itzik Ben-Gan 的SQL Server 2012 T-SQL Fundamentals。奥托尔指出:
SQL 在不同的语言元素中对 UNKNOWN 有不同的处理方式
所以,我浏览了 SQL Server 文档,特别是WHEREclause,但找不到任何关于如何NULL/UNKNOWN处理的具体信息。
有人可以指出我正确的文档或指出我在文档中读错的内容吗?(我高度怀疑我的问题的答案深藏在 SQL 标准的某个地方,但对我来说可能太复杂了,至少在这一点上。)
我有这个表定义:
CREATE TABLE `media` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`brands_id` int(11) DEFAULT NULL,
`media_type` varchar(45) COLLATE utf8_unicode_ci DEFAULT NULL,
`title` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`description` longtext COLLATE utf8_unicode_ci NOT NULL,
`thumbnail_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`media_url` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`media_code` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`inactive` tinyint(1) NOT NULL,
`createdAt` datetime NOT NULL,
`updatedAt` datetime NOT NULL,
`titleHtml` varchar(45) COLLATE utf8_unicode_ci NOT NULL,
`descriptionHtml` longtext COLLATE utf8_unicode_ci NOT NULL,
`useHtml` tinyint(1) NOT NULL,
PRIMARY KEY …Run Code Online (Sandbox Code Playgroud) 我的表中有两个字段:A int, B int。我想添加两个使用这两个字段& 的计算字段 ( CF1& CF2) 。AB
CF1 = (case when [A]>[B] then (CF1=3) else case when [A]<[B] then (CF1=0) else (CF1=1) end end)
CF2 = (case when [A]<[B] then (CF2=3) else case when [A]>[B] then (CF2=0) else (CF2=1) end end)
Run Code Online (Sandbox Code Playgroud)
这工作正常,但是当两个字段 ( A& B) 是NULL,CF1并且CF2是 = 1 时。如何避免这种情况?我的意思是,当领域中的任意一个A或者B是NULL,无论CF1和CF2也应该是NULL。
换句话说:应该只有在0,1或3的值CF1和 …
我决定使用可为空字段或 jsonb 来存储用户配置文件。最初,这将用于联系人:email和phone。我预计稍后可能会添加其他列,例如mobile和website。此外,可能还有其他不相关的字段,例如设置/首选项、保存的搜索等。
我已经决定我不想为此使用任何形式的键值存储(或任何涉及多对多关系的模式),除非有非常好的理由。
jsonb 的优点:
jsonb 的缺点:
还有什么要添加到这个优点/缺点列表中的吗?尽管我只想使用可为空的列,但我认为忽略 jsonb 是一种疏忽 - 这似乎是一个令人信服的选择。
在这个答案中,Erwin Brandstetter 说:
count(step OR NULL) OVER (ORDER BY date)是最短的语法,也适用于 Postgres 9.3 或更早版本。count()只计算非空值。在现代 Postgres 中,更简洁、等效的语法是:Run Code Online (Sandbox Code Playgroud)count(step) FILTER (WHERE step) OVER (ORDER BY date)
我不确定为什么count(step OR NULL)是首选。在我的查询中,我执行以下操作。我重命名了我的变量以匹配他的同时保持语法。
CASE WHEN lag(id_type) OVER (ORDER BY date) <> id_type THEN 1 END AS step
Run Code Online (Sandbox Code Playgroud)
我们正在计算它返回的值。请注意,case 只能返回 1 或 null。
欧文的回答是:
这假设涉及的列是
NOT NULL. 否则你需要做更多。
所以我更迷茫了。添加count(step OR NULL)什么来保护我们的查询有什么意义?
任何人都可以分解这一点,也许可以展示两个带有数据的示例,其中只有一个 - 一个 -count(x OR NULL)有效?
我有一张road_age_test桌子:
create table road_age_test (
surface_year int,
base_year int
);
insert into road_age_test (surface_year, base_year) values (10,20);
insert into road_age_test (surface_year, base_year) values (30,null);
insert into road_age_test (surface_year, base_year) values (null,40);
insert into road_age_test (surface_year, base_year) values (null,null);
insert into road_age_test (surface_year, base_year) values (50,50);
commit;
select * from road_age_test;
SURFACE_YEAR BASE_YEAR
------------ ----------
10 20
30 null
null 40
null null
50 50
Run Code Online (Sandbox Code Playgroud)
我想从每一列中选择最大值,即使其中一个值为空:
GREATEST_YEAR
-------------
20
30
40
null
50
Run Code Online (Sandbox Code Playgroud)
什么是最简单的方法来做到这一点?
注意:如果两个值都是null,我想返回null, …
连接运算符||可以连接任何字符串类型的值,返回text. 在 Postgres 中,每种类型都有一个文本表示并且可以转换为text. 因此,引用手册:
但是,字符串连接运算符 (
||) 仍然接受非字符串输入,只要至少一个输入是字符串类型
有关的:
连接一个或多个NULL值产生结果NULL。
test=# SELECT (text 'foo' || NULL) IS NULL
test-# , (text 'bar' || char '1' || NULL ) IS NULL
test-# , (NULL::bigint || text 'baz') IS NULL;
?column? | ?column? | ?column?
----------+----------+----------
t | t | t
Run Code Online (Sandbox Code Playgroud)
是否可以连接 atext和 aNULL值并获得非空结果?
换句话说, …
我有一个简单的分层表。假设它有这些列:
Id, [Guid], ParentId, Title
Run Code Online (Sandbox Code Playgroud)
只有可以ParentId为空。其他列不可为空。
我创建了一个递归查询来显示从节点到根的路径。为此,我使用了 CTE。这是我的查询:
with Anchor (Id, [Guid], ParentId, Title, [Path])
as
(
select Id, [Guid], ParentId, Title, cast('' as nvarchar(100)) as [Path]
from Hierarchies
where ParentId is null
union all
select Hierarchies.Id, Hierarchies.[Guid], Hierarchies.ParentId, Hierarchies.Title, cast(Anchor.[Path] + '/' + Hierarchies.Title as nvarchar(100)) as [Path]
from Hierarchies
inner join Anchor
on Hierarchies.ParentId = Anchor.Id
)
select
isnull(Anchor.Id, 0) as Id,
isnull(Anchor.[Guid], newid()) as [Guid],
Anchor.ParentId,
Anchor.Title,
Anchor.[Path]
from Anchor
Run Code Online (Sandbox Code Playgroud)
问题是,当我将此查询转换为视图时,该Guid列变为可以为空。我什至使用isnull()函数来强制它不为空。令我惊讶的是,这 …
null ×10
postgresql ×3
sql-server ×3
concat ×1
constraint ×1
count ×1
cte ×1
index ×1
insert ×1
json ×1
mariadb ×1
mysql ×1
oracle ×1
oracle-12c ×1
order-by ×1
performance ×1
recursive ×1
schema ×1
select ×1
t-sql ×1
update ×1