Возможно ли иметь оператор вроде
SELECT "Hello world"
WHERE 1 = 1
в SQL?
Главное, что я хочу знать, это я могу выбрать из ничего, т.е. не иметь предложение FROM.
Возможно ли иметь оператор вроде
SELECT "Hello world"
WHERE 1 = 1
в SQL?
Главное, что я хочу знать, это я могу выбрать из ничего, т.е. не иметь предложение FROM.
Это не согласовано между поставщиками - поддержка Oracle, MySQL и DB2 двойственна:
SELECT 'Hello world'
FROM DUAL
... в то время как SQL Server, PostgreSQL и SQLite не требуют FROM DUAL
:
SELECT 'Hello world'
MySQL поддерживает оба способа.
В Oracle:
SELECT 'Hello world' FROM dual
Двойной эквивалент в SQL Server:
SELECT 'Hello world'
Попробуйте это.
Single:
SELECT * FROM (VALUES ('Hello world')) t1 (col1) WHERE 1 = 1
Матричный:
SELECT * FROM (VALUES ('Hello world'),('Hello world'),('Hello world')) t1 (col1) WHERE 1 = 1
подробнее здесь: http://modern-sql.com/use-case/select-without-from
В типе SQL Server:
Select 'Your Text'
Нет необходимости в FROM
или WHERE
.
Вы можете. Я использую следующие строки в Запрос проводника данных StackExchange:
SELECT
(SELECT COUNT(*) FROM VotesOnPosts WHERE VoteTypeName = 'UpMod' AND UserId = @UserID AND PostTypeId = 2) AS TotalUpVotes,
(SELECT COUNT(*) FROM Answers WHERE UserId = @UserID) AS TotalAnswers
В обмене данными используется Transact-SQL (проприетарные расширения SQL Server для SQL).
Вы можете попробовать это самостоятельно, выполнив запрос типа:
SELECT 'Hello world'
Вот наиболее полный список поддержки базы данных dual из https://blog.jooq.org/tag/dual-table/:
Во многих других СУБД нет необходимости в фиктивных таблицах, так как вы можете выпускать такие утверждения:
SELECT 1; SELECT 1 + 1; SELECT SQRT(2);
Это СУБД, где, как правило, это возможно:
- H2
- MySQL
- Энгр
- Postgres
- SQLite
- SQL Server
- Sybase ASE
В других СУБД требуются фиктивные таблицы, например, в Oracle. Следовательно, вам нужно написать такие вещи:
SELECT 1 FROM DUAL; SELECT 1 + 1 FROM DUAL; SELECT SQRT(2) FROM DUAL;
Это СУБД и их соответствующие фиктивные таблицы:
- DB2: SYSIBM.DUAL
- Derby: SYSIBM.SYSDUMMY1
- H2: Опционально поддерживает DUAL
- HSQLDB: INFORMATION_SCHEMA.SYSTEM_USERS
- MySQL: необязательно поддерживает DUAL
- Oracle: DUAL
- Sybase SQL Anywhere: SYS.DUMMY
У Ingres нет DUAL, но на самом деле это нужно, как в Ingres, вы не можете иметь предложение WHERE, GROUP BY или HAVING без предложения FROM.
В стандартном SQL, нет. Предложение WHERE
подразумевает табличное выражение.
Из спецификации SQL-92:
7.6 "where clause"
Функция
Укажите таблицу, полученную применение "условия поиска" к результат предыдущего "из пункт".
В свою очередь:
7.4 "из предложения"
Функция
Укажите таблицу, полученную из одной или нескольких названных таблиц.
Стандартный способ сделать это (т.е. работать с любым продуктом SQL):
SELECT DISTINCT 'Hello world' AS new_value
FROM AnyTableWithOneOrMoreRows
WHERE 1 = 1;
... если вы хотите изменить предложение WHERE
на нечто более значимое, в противном случае его можно опустить.
Я думаю, что это невозможно. Теоретически: select выполняет два вида вещей:
сузить/расширить набор (теория множеств);
отображение результата.
Первый можно рассматривать как горизонтальное уменьшение, противоположное предложению where-where, которое можно рассматривать как уменьшение по вертикали. С другой стороны, соединение может увеличивать набор по горизонтали, когда объединение может увеличивать набор по вертикали.
augmentation diminishing
horizontal join/select select
vertical union where/inner-join
Второй - это отображение. Отображение - это скорее конвертер. В SQL он принимает несколько полей и возвращает ноль или более полей. В элементе select вы можете использовать некоторые агрегированные функции, такие как sum, avg и т.д. Или взять все значения столбца и преобразовать их в строку. В С# linq мы говорим, что select принимает объект типа T и возвращает объект типа U.
Я думаю, что путаница возникает из-за того, что вы можете сделать: select 'howdy' from <table_name>
. Эта функция является отображением, частью конвертера выбора. Вы ничего не печатаете, а конвертируете! В вашем примере:
SELECT "
WHERE 1 = 1
вы не конвертируете ничего /null в "Hello world"
и сужаете набор ничто/нет таблицы в одну строку, что imho не имеет никакого смысла.
Вы можете заметить, что если вы не ограничиваете количество столбцов, "Hello world"
печатается для каждой доступной строки в таблице. Надеюсь, вы понимаете, почему к настоящему времени. Ваш выбор не принимает ничего из доступных столбцов и создает один столбец с текстом: "Hello world"
.
Итак, мой ответ НЕТ. Вы не можете просто отказаться от предложения from, потому что для выбора всегда требуются столбцы-столбцы.
Для ClickHouse ничего нет system.one
SELECT 1 FROM system.one
Существует и другая возможность - автономные VALUES()
:
VALUES ('Hello World');
Выход:
column1
Hello World
Это полезно, когда вам нужно указать несколько значений в компактном виде:
VALUES (1, 'a'), (2, 'b'), (3, 'c');
Выход:
column1 column2
1 a
2 b
3 c
Этот синтаксис поддерживается SQLite/PostgreSQL/DB LUW/MariaDB 10.3.
Я знаю, что это старый вопрос, но лучшим решением для вашего вопроса является использование подмассива:
SELECT 'Hello World'
FROM (SELECT name='Nothing') n
WHERE 1=1
Таким образом, вы можете иметь WHERE и любое предложение (например, "Соединения" или "Применить" и т.д.) после оператора select, поскольку фиктивный подзапрос принудительно использует предложение FROM без изменения результата.
Я использую firebird. Прежде всего, создайте одну таблицу столбцов с именем "NoTable", как это
CREATE TABLE NOTABLE
(
NOCOLUMN INTEGER
);
INSERT INTO NOTABLE VALUES (0); -- You can put any value
теперь вы можете написать это
select 'hello world' as name
от известных
вы можете добавить любой столбец, который вы хотите показать
В Firebird вы можете сделать это:
select "Hello world" from RDB$DATABASE;
RDB $ DATABASE - это специальная таблица, которая всегда имеет одну строку.
Для DB2:
'VALUES('Hello world')'
Вы также можете сделать несколько "строк":
'VALUES('Hello world'),('Goodbye world');'
Вы даже можете использовать их в соединениях, если типы совпадают:
VALUES(1,'Hello world')
UNION ALL
VALUES(2,'Goodbye world');