Рубрики
sql Без рубрики

ASSERT

Оператор ASSERT используется для проверки определённых условий. Это оператор будет выполняться для каждой строки из набора данных.

Типичный пример, когда можно встретить этот оператор — проверка условия CHECK. Например, для столба можно ограничить список возможных значений. Тогда при вставке данных ASSERT будет проверять для каждой строки значение, переданное в столбец. К сожалению в реальной работе эти возможности SQL используют реже, чем следует. Поэтому мы рассмотрим выдуманный и сильно упрощённый пример.

DROP TABLE IF EXISTS traffic_light;
CREATE TABLE traffic_light
(
    id INT IDENTITY(1, 1),
    color CHAR(1),
    CONSTRAINT CHECK_COLOR CHECK (color IN ( 'G', 'R' ))
);
INSERT INTO dbo.traffic_light (color) VALUES ('Y');

В этой таблице мы разрешаем цвету условного светофора быть или зелёным, или красным. При вставке данных в эту таблицу SQL Server генерирует следующий план:

Если разобраться с тем, что именно проверяет ASSERT, то мы увидим, что он возвращает 0, если в столбец color передаётся значение отличное от G или R и NULL в противном случае. Ошибка будет сгенерирована, есть ASSERT вернёт значение отличное от NULL.

Помимо проверки CHECK-ограничений ASSERT используется и при проверке ограничений внешних ключей. Попробуем чуть усложнить наш пример, добавив ещё одну таблицу с потенциально возможными цветами светофора и связав две таблицы между собой.

DROP TABLE IF EXISTS possible_light;
CREATE TABLE possible_light
(
    color CHAR(1) PRIMARY KEY
);
INSERT INTO dbo.possible_light (color) VALUES ('R'),('Y'),('G');
ALTER TABLE dbo.traffic_light
ADD CONSTRAINT fk_light
    FOREIGN KEY (color)
    REFERENCES dbo.possible_light (color);

Теперь при вставке данных в первую таблицу план усложнится:

Если идти справа налево, то первый ASSERT как и раньше проверит CHECK ограничение, а второй ASSERT проверит корректность связи по ключам.

В предикате второго оператора ASSERT мы видим непонятное условие Expr1007, но всё станет на свои места, если отобразить план запроса в виде текста:

  |--Assert(WHERE:(CASE WHEN NOT [Pass1008] AND [Expr1007] IS NULL THEN (0) ELSE NULL END))
       |--Nested Loops(Left Semi Join, PASSTHRU:([lessons].[dbo].[traffic_light].[color] IS NULL), OUTER REFERENCES:([lessons].[dbo].[traffic_light].[color]), DEFINE:([Expr1007] = [PROBE VALUE]))
            |--Assert(WHERE:(CASE WHEN [lessons].[dbo].[traffic_light].[color]<>'R' AND [lessons].[dbo].[traffic_light].[color]<>'G' THEN (0) ELSE NULL END))
            |    |--Table Insert(OBJECT:([lessons].[dbo].[traffic_light]), SET:([lessons].[dbo].[traffic_light].[color] = [Expr1004],[lessons].[dbo].[traffic_light].[id] = [Expr1003]))
            |         |--Compute Scalar(DEFINE:([Expr1004]=CONVERT_IMPLICIT(char(1),[@1],0)))
            |              |--Compute Scalar(DEFINE:([Expr1003]=getidentity((1525580473),(6),NULL)))
            |                   |--Constant Scan
            |--Clustered Index Seek(OBJECT:([lessons].[dbo].[possible_light].[PK__possible__900DC6E8209DDE1B]), SEEK:([lessons].[dbo].[possible_light].[color]=[lessons].[dbo].[traffic_light].[color]) ORDERED FORWARD)

По строке DEFINE:([Expr1007] = [PROBE VALUE]) становится понятно, что это выражение — просто результат объединения таблиц. Этим выражением ASSERT проверяет, что вставляемое значение действительно есть в таблице possible_light.

Наконец, рассмотрим ещё один случай, где оператор ASSERT может встречаться в реальной работе. Речь идёт о подзапросах. Во многих ситуациях встречается «скалярный» подзапрос. Т.е. такой подзапрос, который возвращает строго одно значение. В качестве тестового запроса рассмотрим следующий код:

SELECT * FROM dbo.traffic_light tl
WHERE (tl.color>
(SELECT pl.color FROM dbo.possible_light pl WHERE (1=1)and(pl.color>'A'))
)

Практического смысла он не несёт, но позволяет продемонстрировать ситуацию, когда мы сравниваем скалярное значение с результатом подзапроса. План получился не очень сложный:

Самый интересный блок тут это часть где данные из possible_light агрегируются, чтобы подсчитать количество строк, а потом полученное значение передаётся в ASSERT. Думаю, вы уже сами догадались, что Expr1004 это результат агрегации

Stream Aggregate(DEFINE:([Expr1004]=Count(*)...

Вот такой большой пост у меня получился о простейшем, но очень важном операторе.

Рубрики
wosb_freshwater Без рубрики

Caridina golden dragon

Торговое название этой креветки «золотой дракон». Почему «золотой» понятно, но вот про «дракона» я не понял. Если у вас есть версия, пишите в комментариях. Относится к селекционным видам. В остальном ничего особенного. Обычная креветка-каридина.

Рубрики
photoblog Без рубрики

2022-10-17

В горы ходить вообще не круто.

Рубрики
photoblog Без рубрики

2022-10-16

Рубрики
wosb_freshwater Без рубрики

Thorichthys ellioti

Цихлазома Элиота — американская цихлида, живущая в медленных реках Мексики. Эти рыбы чаще всего живут стаями недалеко от берега. Их удивительная красота и необычный внешний вид сделали этих рыб любимцами аквариумистов. К сожалению, содержать этих рыб в аквариуме с растениями довольно тяжело, так как цихлазомы ищут корм, просеивая грунт. Если вы хотите попробовать разводить рыб, то цихлазомы Элиота — отличный выбор. Они легко нерестятся и долго ухаживают за мальком, защищая его от других рыб.

Рубрики
wosb_freshwater Без рубрики

Caridina sp. (Galaxy fishbone)

Помимо морских аквариумов, я содержу ещё и пресноводных креветок. На фото относительно редкая креветка из рода Caridina. Коллекционеры называют эту расцветку Galaxy (потому что есть точки, похожие на звёзды) Fishbone (рисунок на спине напоминает скелет рыбы). Недавно у меня впервые появились мальки этих креветок.

Рубрики
photoblog Без рубрики

2022-10-05

Рубрики
blogpost Без рубрики

Список моих питомцев

Иногда меня спрашивают, сколько всего у меня кораллов, рыбок, креветок и других животных. По правде говоря, я и сам этого точно не знаю, поэтому я решил как-то систематизировать всех, кого я содержал ранее, или содержу сейчас. Получилась интерактивная схема, которая позволяет не только приблизительно ответить на вопрос из начала статьи, но и оценить как далеко мои питомцы находятся друг от друга на филогенетическом дереве. Буду рад любым комментариям или предложениям по улучшению — https://agorkov.ru/biota/

Рубрики
wosb_freshwater Без рубрики

Бактериальная слизь под микроскопом

В течение нескольких недель на канале моих друзей из BioBox проходил интересный марафон. В кубиках Aquael Shrimp Set создавали различные биотопы: флорариум, палюдариум и аквариум. Буквально вчера я посещал их студию и видел получившийся аквариум. Видео о нём вы можете посмотреть ниже:

Как и в большинстве аквариумов коряга там покрылась белым слоем бактериальной слизи. Выглядит это примерно так:

Опыт говорит, что вреда от слизи нет, но любопытство берёт своё. Я сделал соскобы и поехал домой, изучать их под микроскопом. Сам не знаю почему, но я ожидал увидеть там много диатомовых водорослей. Они, конечно, присутствовали, но гораздо больше там было инфузорий. Может, кто-то даже возьмётся определить конкретный вид:

Рубрики
wosb_freshwater Без рубрики

Neocaridina rili(?)

Современные аквариумные креветки — результат долгой селекционной работы. Иногда в потомстве от коллекционных креветок проскакивают такие странные особи. Специалисты называют их отбраковкой, а мне такие наоборот нравятся.