Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: Странное поведение при сравнении int и null

Добрый день!

Таблица:

Код
--
-- Структура таблицы `test5`
--

CREATE TABLE IF NOT EXISTS `test5` (
  `col_1` int(11) DEFAULT NULL,
  `col_2` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Дамп данных таблицы `test5`
--

INSERT INTO `test5` (`col_1`, `col_2`) VALUES
(1, NULL),
(2, 2),
(3, 333);


Запрос:

Код
SELECT * FROM test5 WHERE col_1 != col_2


Результат:

Код
col_1    col_2
3    333


Побочный результат:

:shok  :wacko  :dash1 

Это нормально, что при WHERE col_1 != col_2 MySQL не считает что 1 != NULL ?

И как быть???

Это сообщение отредактировал(а) maxipub - 2.11.2016, 14:17
Ответ:
Цитата(maxipub @  3.11.2016,  11:52 )
зачем так делать?

Порассуждали в курилке с пацанами на тему: "зачем бы в SQL использовалась трехзначная логика, коли от нее одни лишь проблемы".
Пофантазировали на тему что было бы, будь она двузначна. Решили что было бы очень плохо. Если предполагать за Null неопределенное значение, то неопределенность мы можем сравнивать лишь на равенство(=) и строгое неравенство (!=). Операции "больше", "меньше", "между" с неопределенным значением возвращать должны неопределенный результат, а значит, в двузначной логике не представимы. Реализация двузначной логики привела бы к тому, что операции сравнения были бы запрещены для применения к наборам, содержащим неопределенные значения. Ввод третьего состояния логики решает эту проблему, но имеет свою цену в виде так не любимого всеми правила, что все операции сравнения с неопределенностью приводят к неизвестному результату.


Это сообщение отредактировал(а) Zloxa - 3.11.2016, 12:59
Вопрос: Странное поведение null not in (...)

Приветствую.
Столкнулся тут со странной логикой Oracle.
Вот её сухой остаток:

SQL> Select * from V$Version;

BANNER
----------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE 11.2.0.2.0 Production
TNS for Linux: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production

SQL> Select 1 from dual where null not in (Select null from dual where 1=1);

строки не выбраны

SQL> Select 1 from dual where null not in (Select null from dual where 1=2);

1
----------
1

Как объяснить последний результат в свете парадигмы, что любая логическая операция с null даёт null?
Ответ: хм...хм..,

отсутствие строк = no rows (в подзапросе).
Вопрос: CDC: Странное поведение при create database for attach

Всем привет!

Microsoft SQL Server 2014 - 12.0.4422.0 (X64)
Jul 27 2015 16:56:19
Copyright (c) Microsoft Corporation
Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)

Странное поведение CDC при create database for attach

Суть: Есть DB в 0,6TB c CDC enabled. Детачим БД, делаем RW клон средствами СХД, аттачим (create database ... for attach)

Проблематика:

у источника: is_cdc_enabled = 1 в sys.databases, в Management studio - Change Tracking = True
у копии: is_cdc_enabled = 0, - Change Tracking = True
Исходя из этого CDC не включено на копии.

sys.sp_cdc_enable_db: the database 'XXXXXXX' cannot be enabled for Change Data Capture because a database user named 'cdc' or a schema named 'cdc' already exists in the current database.
sys.sp_cdc_disable_db: The database 'XXXXXXX' is not enabled for Change Data Capture

В синтаксисе рестора есть KEEP_CDC, в синтаксисе - create databse for attach - нет такого параметра.

Пока вижу единственное решение: определение таблиц в включенным CDC, сохранением объектов (values,index,keys,triggers) в DynSQL ним, drop схемы, пользователя cdc, авторизации как вот , включение CDC (sp_cdc_enable_db), включение CDC на таблицах, рестор из DynSQL

Вопрос: Есть какое-нибудь более простое решение?

p.s. Профит от всего этого такой: Рестор базы ~2часа, создание RW клона диска на уровне операционки+аттач ~1 минута. Клонов диска может быть до 255.
Ответ: Вот это да.

В скрипте восстановления БД (powershell) сразу после
$sql = "create ... for attach"
invoke-sqlcmd $sql

Следовали инструкции
$sql = "use db;EXEC sys.sp_cdc_drop_job @job_type = N'capture'; EXEC sys.sp_cdc_add_job @job_type = N'capture';"
Invoke-sqlcm $sql

Несмотря на то что они в различных транзакциях происходил какой-то конфликт.

Вставка небольшой задержки в 1 минутку между блоками решила проблему
Вопрос: странное поведение oracle sql developer, сравнение дат

помогите разобраться, в чем проблема. Вот этот запрос
select alert_date
FROM alert a
WHERE a.alert_date > to_timestamp('10/01/1920', 'mm/dd/yyyy')

возвращает данные нормально, а этот
select alert_date
FROM alert a
WHERE a.alert_date > nvl(:start_date, to_timestamp('10/01/1920', 'mm/dd/yyyy'))

при подстановке null не возвращает ничего. Причем экспериментально выяснил, что второй запрос 1920 преобразует к 2020, из-за чего данных и нет. NLS_DATE/TIMESTAMP_FORMAT базы dd-mon-rr. Если выставить nls форматы в mm/dd/yyyy в сессии, все чудесным образом начинает работать правильно. Это какая-то фишка sql developer'а или я что-то не так делаю?
Ответ: to_date(null) никто не отменял
Вопрос: Странное поведение into с XML

Обнаружил сегодня странную вещь на своем MSSQL.
Вот такой вот код выдает результат "Rifts 1", вместо 1 может быть цифра от 0 до 3 случайным образом.
Хотя должен выдавать "Rifts NULL".
Если убрать into #ExpTables, identity(1,1) или вместо tb.id написать tb.id+0 - начинает выдавать все правильно.
Подскажите пожалуйста как такое может быть? Сломал голову напрочь.
create table TTables(ID int not null identity(1,1),NAME varchar(200) not null);

declare @xml xml;
select @xml='<Table><NAME>Rifts</NAME></Table>';

select T.c.value('NAME[1]','varchar(200)') as NAME, tb.id as TID
into #ExpTables
from @xml.nodes('/Table') AS T(c)
     left join TTables tb on tb.name=T.c.value('NAME[1]','varchar(200)');

select * from #ExpTables;

drop table #ExpTables;
drop table TTables;

Версия SQL 9.00.5324.00 (X64) Standard Edition (64-bit)
Ответ: Rifts 598917104

Как-то так выдает на

Microsoft SQL Server 2005 - 9.00.5057.00 (Intel X86) Mar 25 2011 13:50:04 Copyright (c) 1988-2005 Microsoft Corporation Developer Edition on Windows NT 5.2 (Build 3790: Service Pack 2)

И вот так

Msg 681, Level 16, State 3, Line 6
Attempting to set a non-NULL-able column's value to NULL.

На
Microsoft SQL Server 2008 (SP4) - 10.0.6241.0 (Intel X86) Apr 17 2015 11:02:30 Copyright (c) 1988-2008 Microsoft Corporation Enterprise Edition on Windows NT 5.2 <X86> (Build : )
Вопрос: Странный результат последовательности delete + update

Наткнулся на странное поведение при последовательных delete и update в одной транзакции.

Есть табличка с деревом и 2мя порядками для детей:
CREATE TABLE SYMPTOMS (
  ID D_ID,
  PARENT_ID D_ID_OR_NULL,
  ORD_NUM_EN D_NUM,
  ORD_NUM_RU D_NUM,
  -- Много всякого
  PRIMARY KEY (ID),
  FOREIGN KEY (PARENT_ID) REFERENCES SYMPTOMS (ID) ON DELETE CASCADE
);

В порядках не должно быть дырок.
Вот один из наборов детей:
+

select r.ID, r.PARENT_ID, r.ORD_NUM_EN, r.ORD_NUM_RU
from SYMPTOMS r
where r.PARENT_ID = 470108
order by r.ORD_NUM

ID PARENT_ID ORD_NUM_EN ORD_NUM_RU
653027 470108 1 1
653026 470108 2 2
653025 470108 3 3
653024 470108 4 4
653023 470108 5 5
653022 470108 6 10
653021 470108 7 13
653020 470108 8 17
470109 470108 9 19
653019 470108 10 9
653018 470108 11 11
470110 470108 12 6
470111 470108 13 7
653017 470108 14 12
653016 470108 15 18
470113 470108 16 14
653015 470108 17 15
653014 470108 18 16
470114 470108 19 8


Одна из операций - удаление детей по некоторому условию.
Если условие выполняется, строка удаляется, а у остальных корректируется порядки.
Вся операция происходит в одной транзакции.
(псевдокод):
def del_some_child(connection, parent_id, mast_del):
  curs = connection.Cursor()
  curs.execute('select ID, ORD_NUM_EN, ORD_NUM_RU from SYMPTOMS where PARENT_ID = ? order by ORD_NUM_EN', [parent_id])
  childs = [(cid, ne, nr) for cid, ne, nr in curs]
  for cid, n in childs:
    if mast_del(cid):
      curs.execute('delete from SYMPTOMS where ID = ?', [cid])
      curs.execute(
        'update SYMPTOMS set ORD_NUM_EN = ORD_NUM_EN - 1 where PARENT_ID = ? and ORD_NUM_EN > ?', [parent_id, ne])
      curs.execute(
        'update SYMPTOMS set ORD_NUM_RU = ORD_NUM_RU - 1 where PARENT_ID = ? and ORD_NUM_RU > ?', [parent_id, nr])
  connection.commit()

В результате порядки получаются несколько странные:
ID PARENT_ID ORD_NUM_EN ORD_NUM_RU
470109 470108 5 11
470110 470108 6 3
470111 470108 7 4
470113 470108 8 9
470114 470108 10 4

Если идти по детям в обратном порядке (order by ORD_NUM_EN desc), то ORD_NUM_EN получается правильный, а ORD_NUM_RU - какой попало...

Кто-нибудь может объяснить такое странное поведение?
Ответ: Не столько ответ, сколько для истории
Tonal
Значения ORD_NUM-ов берутся старые, до того как начали отрабатывать delete/update.
Чтобы заработало как задумано нужны актуальные. т. е. их нужно перезапрашивать.

Эта проблема была бы замечена если в исходном сообщении был бы пример лямбды mast_del, который не передаёт конкретный id, а передаёт условие cid > ...
Можно и по данным догадаться, но я вот, например, попался :)
На Питон грешить тут действительно нечего, потому как при
childs = [(cid, ne, nr) for cid, ne, nr in curs]
выборка полностью фетчится и материализуется (особенности списочных выражений в Питоне, сам драйвер так и делает при fetchall).
Tonal
Ну а на Python-е я вовсе по другому сделал - собрал всех оставшихся в список, отсортировал как надь и восстановил нумерацию.

Я не знаю природы данных и их распределения для таких запросов, но может получится, что будет много апдейтов уже "приговорённых" записей, подпадающих под условие. Может лучше сделать процедуру ..._renumerate(id), которая в 2 прохода перенумерует записи. Для FB3.0 можно будет писать так:
merge into symptoms s
using (
    select s.id, count(*) over (order by s.ord_num_en) as ord_num_en, count(*) over (order by s.ord_num_ru) as ord_num_ru from symptoms s
) as s_new on s_new.id = s.id
when matched
  -- 1. дополнительное условие если нужно исключить холостые update
  -- 2. is distinct from для корректной обработки null-ов (не в данном случае, а вообще)
  and ( s.ord_num_en is distinct from s_new.ord_num_en
        or
        s.ord_num_ru is distinct from s_new.ord_num_ru
      )
  then update
    set
    s.ord_num_en = s_new.ord_num_en,
    s.ord_num_ru = s_new.ord_num_ru
Вопрос: Странное поведение phpmyadmin

При снятии дампа с mysql через phpmyadmin получаю на выходе
Код MySQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
DROP TABLE IF EXISTS `files`;
CREATE TABLE IF NOT EXISTS `files` (
  `disk` varchar(255) default NULL,
  `hl` varchar(255) default NULL,
  `ll` varchar(255) default NULL,
  `extensions` varchar(255) default NULL,
  `date` datetime default NULL,
  `size` double default NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
INSERT INTO `files` VALUES ('C:', '\\Users\\admin\\Documents\\filemonsql\\dir\\', 'files', '.xml', '2015-08-07 11:13:00', 389);
INSERT INTO `files` VALUES ('C:', '\\Users\\admin\\Documents\\filemonsql\\dir\\', '07.08.2015', '.xml', '2015-08-07 16:04:00', 561);
INSERT INTO `files` VALUES ('C:', '\\Users\\admin\\Documents\\filemonsql\\', 'mysqldump', '.exe', '2008-02-13 13:00:00', 2146944);
INSERT INTO `files` VALUES ('C:', '\\Users\\admin\\Documents\\filemonsql\\', 'files', '.sql', '2015-08-07 11:35:00', 0);
INSERT INTO `files` VALUES ('C:', '\\Users\\admin\\Documents\\filemonsql\\', 'DirToXML', '.bat', '2015-08-07 15:59:00', 5375);
INSERT INTO `files` VALUES ('C:', '\\Users\\admin\\Documents\\filemonsql\\dir\\', 'files', '.xml', '2015-08-07 11:13:00', 389);
Но когда при помощи скрипта
Код Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
chcp 65001
echo -- > C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo DROP TABLE IF EXISTS `files`; >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo CREATE TABLE IF NOT EXISTS `files` ( >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo   `disk` varchar(255) default NULL, >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo   `hl` varchar(255) default NULL, >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo   `ll` varchar(255) default NULL, >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo   `extensions` varchar(255) default NULL, >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo   `date` datetime default NULL, >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo   `size` double default NULL >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
echo ) ENGINE=MyISAM DEFAULT CHARSET=utf8; >> C:\Users\admin\Documents\filemonsql\dir\%date%.sql
 
 for /f "delims=" %%a in ('dir %1 /S /B /A:-D-L') do @(
 >nul ping -n 1 -w 1 ""
 >>"C:\Users\admin\Documents\filemonsql\dir\%date%.sql" echo INSERT INTO `files` VALUES ('%%~da', '\%%~pa\', '%%~na', '%%~xa', '%%~ta', %%~za^)^;
 )
@pause
Собираю содержимое каталога или диска, то на выходе получаю немного отличающуюся информацию:
Код MySQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DROP TABLE IF EXISTS `files`; 
CREATE TABLE IF NOT EXISTS `files` ( 
  `disk` varchar(255) default NULL, 
  `hl` varchar(255) default NULL, 
  `ll` varchar(255) default NULL, 
  `extensions` varchar(255) default NULL, 
  `date` datetime default NULL, 
  `size` double default NULL 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\\', '07.08.2015', '.sql', '07.08.2015 16:11', 557);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\\', 'DirToXML', '.bat', '11.08.2015 15:59', 5001);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\\', 'DirToXML_rezerv', '.bat', '07.08.2015 15:59', 5375);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\\', 'impotTOmysql', '.bat', '07.08.2015 16:42', 389);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\\', 'mysql', '.bat', '07.08.2015 16:53', 56);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\\', 'mysqldump', '.exe', '13.02.2008 13:00', 2146944);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\\', 'spy off', '.bat', '10.08.2015 16:37', 3955);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\dir\\', '10.08.2015', '.xml', '11.08.2015 10:19', 37955313);
INSERT INTO `files` VALUES ('C:', '\\Users\admin\Documents\filemonsql\dir\\', '11.08.2015', '.sql', '11.08.2015 16:00', 1370);
При попытке засунуть инструментами phpmyadmin дамп в базу, то в строке с адресом расположения файла пропадают двойные слешы, а одинарный просто пропадает и в бд я имею на выходе следующую строку
Код SQL
1
\UsersadminDocumentsfilemonsqldir\
Что за ерись и как её побороть?
Ответ: В чем велосипед?
Вопрос: Странное поведение при использовании вложенного запроса

Добрый день.
Подскажите в чем может быть ошибка?
Не знаю с чего начать, поэтому начну от проблемы.

Такой запрос выполняется нормально, быстро примерно 125ms
SELECT dst, SUM (sent) AS sent, SUM (rcvd) AS rcvd 
FROM traffic WHERE datetime >= (SELECT now()::date) and src like '192.168.33.1' and dport=53 
GROUP BY dst ORDER BY rcvd DESC;


Следующий запрос не выполняется, точнее заканчивается неудачно по таймауту:
SELECT dst, SUM (sent) AS sent, SUM (rcvd) AS rcvd 
FROM traffic WHERE datetime >= (SELECT now()::date) and src like '192.168.33.1' and dport=1025 
GROUP BY dst ORDER BY rcvd DESC;

Отличается только выбираемым значением dport=1025

Следующий запрос выполняется быстро:
SELECT dst, SUM (sent) AS sent, SUM (rcvd) AS rcvd 
FROM traffic WHERE datetime >= '2017-03-17' and src like '192.168.33.1' and dport=1025 
GROUP BY dst ORDER BY rcvd DESC;

Отличается от предыдущего отсутствием вложенного запроса (datetime >= '2017-03-17')

СУБД postgres (PostgreSQL) 9.4.10
traflogdb=> \d traffic
                                     Таблица "public.traffic"
 Колонка  |             Тип             |                       Модификаторы
----------+-----------------------------+----------------------------------------------------------
 lineid   | bigint                      | NOT NULL DEFAULT nextval('traffic_lineid_seq'::regclass)
 datetime | timestamp without time zone | NOT NULL
 namedev  | character varying(10)       | NOT NULL
 src      | character varying(16)       | NOT NULL
 sport    | integer                     |
 dst      | character varying(16)       | NOT NULL
 dport    | integer                     |
 message  | character varying(20)       |
 duration | integer                     | NOT NULL
 sent     | integer                     |
 rcvd     | integer                     |
 protoid  | smallint                    | NOT NULL
 proto    | character varying(16)       |
 mac      | character varying(18)       |
Индексы:
    "traffic_pkey" PRIMARY KEY, btree (lineid)
    "traffic_index_datetime" btree (datetime)
    "traffic_index_dport" btree (dport)
    "traffic_index_dst" btree (dst)
    "traffic_index_src" btree (src)

traflogdb=> select pg_table_size('traffic');
 pg_table_size
---------------
    8274214912
(1 строка)
Ответ: Melkij, спасибо за разъяснения.
Попробовал сделать составной индекс src, datetime с таким индексом запросы выполняются заметно быстрее.

Еще несколько вопросов:
1 Подскажите как, будет происходить такое преобразование данных на живой БД ? Можно ли вообще это делать на живой? или лучше на время приостановить insert`ы?
ALTER TABLE traffic_test ALTER COLUMN src TYPE inet USING src::inet ;
ALTER TABLE traffic_test ALTER COLUMN dst TYPE inet USING dst::inet ;
ALTER TABLE traffic_test ALTER COLUMN mac TYPE macaddr USING mac::macaddr ;


2 Я так понимаю после преобразования, для фактического изменения размера БД, надо будет выполнять ANALYZE, VACUUM. Так ли это?

3 Надо ли после преобразования выполнять перестройку индексов или они будут перестраиваться автоматически во время выполнения преобразования?
Вопрос: Странное поведение, не могу объяснить

MSSQL 2008 R2 (10.50.6000)
Есть большая таблица с данными
create table [Table1]
(
     [id] int identity(1,1) not null
    ,[Field1] varchar(16) not null
    ,[Field2] varchar(100) not null
    ,[Field3] varchar(100) not null
    ,[Field4] varchar(3) not null
    ,[DT] datetime not null
    ,constraint [PK_Table1] primary key clustered ([Field1],[Field2],[Field3],[Field4])
)

решил немного исправить кривые данные, сложив результат в пустую таблицу [Table2] такой же структуры
для чего использовал такой скрипт
select
     [Field1]
    ,[Field2] = case when [Field4] = 'ABC' then ''  else [Field2]
    ,[Field3] = case when [Field4] = 'ABC' then ''  else [Field3]
    ,[Field4]
    ,[DT] = min([DT4])
from [Table1]
group by
     [Field1]
    ,case when [Field4] = 'ABC' then ''  else [Field2]
    ,case when [Field4] = 'ABC' then ''  else [Field3]
    ,[Field4]

так вот если использовать Import/Export Wizard - ругается на дубликаты,
а если выполнить скриптом insert into [Table2] - проходит без проблем.
Как это можно объяснить?
Ответ: leov,

Identity в приведенный ключ не входит и не может давать нарушение его уникальности.
Вопрос: Странное поведение Oracle 12c при создании функций/пакетов/процедур с ошибками в тексте

Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production

Выполняю вот такой скрипт
begin
  execute immediate ' create or replace procedure test1_a
is
begin
  null
end; ';
raise_application_error(-20000,'Error');
end;


Скрипт выполняется без ошибок т.е. получается, что выполнение прерывается после execute immediate причем без каких либо сообщений об ошибках.

В 11.2 по моему такого не было.
Этот баг как нибудь лечится?
Ответ: Все разобрался, PL/SQL Developer перехватывает ORA-24344 и в результате создается впечатление что ошибки нет, а сервер без всяких предупреждений прервал выполнение :(