Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
Добрый день, собственно застрял на этом.
Есть таблица1 "Клиенты"
Есть таблица2 "Абонементы"
Нужно в таблицу3 "Клиенты_Абонементы" одним запросом INSERT занести IDКлиента и IDАбонемента.
Вроде кажется просто а уже часа 3,5 сижу и ничего не могу сделать толком....
Подскажите пожалуйста люди добрые, ЧЯДНТ ?
13 окт 13, 14:28    [14962803]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
qwerty112
Guest
libeadier
Подскажите пожалуйста люди добрые, ЧЯДНТ ?

так ты покажи, что ты делаешь, что получаешь (ошибка или просто 0 рекордз аффектед) - тогда можно будет и сказать ЧНТ ...
13 окт 13, 14:34    [14962812]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
Bug69
Member

Откуда: Москва, Чертаново
Сообщений: 229
Выложите скрипты создания таблиц! Какие в них поля, кроме ID? Как логически взаимоувязаны эти таблицы?
13 окт 13, 14:39    [14962819]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
Хотел сделать, что то типа такого
INSERT INTO Clients_Abonements (IDClient, IDAbon)

SELECT top(1)     IDClient
FROM         Clients

SELECT     IDAbon
FROM         Abonement
WHERE     AbonName = 'Выходной'
13 окт 13, 14:39    [14962823]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
qwerty112
Guest
INSERT INTO Clients_Abonements (IDClient, IDAbon)

SELECT top(1)     IDClient, IDAbon
FROM         Clients
cross join       Abonement
WHERE     AbonName = 'Выходной'

это ?
13 окт 13, 14:43    [14962829]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
Bug69
Member

Откуда: Москва, Чертаново
Сообщений: 229
Получается связь многие ко многим.
У вас действительно один клиент владеет несколькими абонементами (что возможно вполне) и один абонемент может принадлежать нескольким клиентам (что весьма сомнительно)?
Расскажите пожалуйста, чего именно вы хотите добиться?
13 окт 13, 14:43    [14962830]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
Bug69,

USE [AIS_helth_center]
GO

/****** Object:  Table [dbo].[Abonement]    Script Date: 10/13/2013 16:41:36 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Abonement](
	[IDAbon] [int] IDENTITY(1,1) NOT NULL,
	[AbonName] [varchar](50) NOT NULL,
	[AbonPrice] [money] NOT NULL,
 CONSTRAINT [PK_Abonement] PRIMARY KEY CLUSTERED 
(
	[IDAbon] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO


USE [AIS_helth_center]
GO

/****** Object:  Table [dbo].[Clients]    Script Date: 10/13/2013 16:42:32 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[Clients](
	[IDClient] [int] IDENTITY(1,1) NOT NULL,
	[Name] [varchar](50) NOT NULL,
	[Surname] [varchar](50) NOT NULL,
	[Phone] [varchar](50) NULL,
	[Birth] [date] NULL,
	[Photo] [image] NULL,
	[Balance] [money] NOT NULL,
 CONSTRAINT [PK_Clients] PRIMARY KEY CLUSTERED 
(
	[IDClient] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO


USE [AIS_helth_center]
GO

/****** Object:  Table [dbo].[Clients_Abonements]    Script Date: 10/13/2013 16:44:07 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[Clients_Abonements](
	[IDClient] [int] NULL,
	[IDAbon] [int] NULL,
	[IDDay] [int] NULL,
	[IDTime] [int] NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Clients_Abonements]  WITH CHECK ADD  CONSTRAINT [FK_Clients_Abonements_Abonement] FOREIGN KEY([IDAbon])
REFERENCES [dbo].[Abonement] ([IDAbon])
GO

ALTER TABLE [dbo].[Clients_Abonements] CHECK CONSTRAINT [FK_Clients_Abonements_Abonement]
GO

ALTER TABLE [dbo].[Clients_Abonements]  WITH CHECK ADD  CONSTRAINT [FK_Clients_Abonements_Clients] FOREIGN KEY([IDClient])
REFERENCES [dbo].[Clients] ([IDClient])
GO

ALTER TABLE [dbo].[Clients_Abonements] CHECK CONSTRAINT [FK_Clients_Abonements_Clients]
GO

ALTER TABLE [dbo].[Clients_Abonements]  WITH CHECK ADD  CONSTRAINT [FK_Clients_Abonements_Days] FOREIGN KEY([IDDay])
REFERENCES [dbo].[Days] ([IDDay])
GO

ALTER TABLE [dbo].[Clients_Abonements] CHECK CONSTRAINT [FK_Clients_Abonements_Days]
GO

ALTER TABLE [dbo].[Clients_Abonements]  WITH CHECK ADD  CONSTRAINT [FK_Clients_Abonements_Times] FOREIGN KEY([IDTime])
REFERENCES [dbo].[Times] ([IDTime])
GO

ALTER TABLE [dbo].[Clients_Abonements] CHECK CONSTRAINT [FK_Clients_Abonements_Times]
GO

ЛОгически связвать эти две таблицы как раз и должна Clients_Abonements
13 окт 13, 14:45    [14962832]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
Bug69
Member

Откуда: Москва, Чертаново
Сообщений: 229
qwerty112
это ?

Сомнительно как-то. Получается, что абонемент "Выходной" раздали сразу всем клиентам.
13 окт 13, 14:45    [14962833]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
Bug69,

1 клиент = 1 абонемент
13 окт 13, 14:45    [14962834]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
Bug69,

нет нет тут возможно все ок. Я данные для WHERE возьму из формы. Работаю в Delphi.\

Сейчас проверю что посоветовал qwerty1234
13 окт 13, 14:47    [14962836]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
qwerty112, Спасибо!! Получилось!!
Теперь если к примеру будет не 2 таблицы, а 5, то нужно будет просто добавить их через CROSS JOIN ?

Так?
INSERT INTO Clients_Abonements
                      (IDClient, IDAbon)
SELECT     TOP (1) Clients.IDClient, Abonement.IDAbon
FROM         Clients CROSS JOIN
                      Abonement
WHERE     (Abonement.AbonName = 'Выходной')
CROSS JOIN
                      Table4
WHERE     (TAble4.Table4Name = 'some')
13 окт 13, 14:51    [14962843]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
libeadier, что то так не получается...Будем искать...
13 окт 13, 14:54    [14962845]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
qwerty112
Guest
libeadier
qwerty112, Спасибо!! Получилось!!
Теперь если к примеру будет не 2 таблицы, а 5, то нужно будет просто добавить их через CROSS JOIN ?

Так?
INSERT INTO Clients_Abonements
                      (IDClient, IDAbon)
SELECT     TOP (1) Clients.IDClient, Abonement.IDAbon
FROM         Clients CROSS JOIN
                      Abonement
WHERE     (Abonement.AbonName = 'Выходной')
CROSS JOIN
                      Table4
WHERE     (TAble4.Table4Name = 'some')

WHERE должно быть одно, и после всей секции FROM
INSERT INTO Clients_Abonements
                      (IDClient, IDAbon)
SELECT     TOP (1) Clients.IDClient, Abonement.IDAbon
FROM         Clients CROSS JOIN
                      Abonement
CROSS JOIN
                      Table4
WHERE     (Abonement.AbonName = 'Выходной')
and     (TAble4.Table4Name = 'some')
13 окт 13, 14:58    [14962849]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
qwerty112, Спасибо огромное!! Дай Бог Вам успехов на долгие годы!!
13 окт 13, 15:03    [14962856]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
Bug69
Member

Откуда: Москва, Чертаново
Сообщений: 229
Насколько я понимаю, одна таблица содержит сведения о клиентах, а вторая о типах абонементов. Третья таблица по сути должна хранить сведения о том, какой клиент какого типа абонемент приобрел. Данные ни одной из этих таблиц не могут генерироваться на основании запросов к другим таблицам. Кроме того, полагаю, что вам необходимо хранить дату продажи абонемента, даты начала и окончания его действия.

Для вставки значений в эту таблицу лучше написать хранимку и юзать ее из приложения.

CREATE TABLE [dbo].[Clients_Abonements]
(
	[IDClient] [int] NULL
	, [IDAbon] [int] NULL
	, [saleDate] datetime NOT NULL
	, [validFrom] datetime NOT NULL
	, [expiredDate] datetime NOT NULL
)
GO


А это хранимка для ввода данных в таблицу:

CREATE PROCEDURE [dbo].[Clients_Abonements_INSERT]
	@idClient int
	, @idAbon int
	, @saleDate datetime
	, @validFrom datetime
	, @expiredDate datetime
AS
	INSERT INTO
		[dbo].[Clients_Abonements]
	(
		[IDClient]
		, [IDAbon]
		, [saleDate]
		, [validFrom]
		, [expiredDate]
	)
	VALUES
	(
		@idClient
		, @idAbon
		, @saleDate
		, @validFrom
		, @expiredDate
	)
GO



Или, если id вам сильно не по душе:

CREATE PROCEDURE [dbo].[Clients_Abonements_INSERT]
	@clientName varchar(50)
	, @abonName varchar(50)
	, @saleDate datetime
	, @validFrom datetime
	, @expiredDate datetime
AS
	DECLARE
		@idClient int
		, @idAbon int
	
	SELECT
		@idClient = [IDClient]
	FROM
		[dbo].[Clients]
	WHERE
		[Name] = @clientName
	
	SELECT
		@idAbon = [IDAbon]
	FROM
		[dbo].[Abonement]
	WHERE
		[AbonName] = @abonName
	
	INSERT INTO
		[dbo].[Clients_Abonements]
	(
		[IDClient]
		, [IDAbon]
		, [saleDate]
		, [validFrom]
		, [expiredDate]
	)
	VALUES
	(
		@idClient
		, @idAbon
		, @saleDate
		, @validFrom
		, @expiredDate
	)
GO
13 окт 13, 15:20    [14962873]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
Bug69
Member

Откуда: Москва, Чертаново
Сообщений: 229
qwerty112
WHERE должно быть одно, и после всей секции FROM
INSERT INTO Clients_Abonements
                      (IDClient, IDAbon)
SELECT     TOP (1) Clients.IDClient, Abonement.IDAbon
FROM         Clients CROSS JOIN
                      Abonement
CROSS JOIN
                      Table4
WHERE     (Abonement.AbonName = 'Выходной')
and     (TAble4.Table4Name = 'some')


Это вообще что?
Не получая ни одного поля из Table4, вставлять ее кроссом в insert?

Вы отдаете себе отчет, что сбили с пути истинного наивного начинающего программиста?
Представьте себе, что если в Table4 пара миллионов строк! Вы понимаете, что произойдет? нет?
Кроме того, даже без Table4 вы понимаете, что делает предложенный Вами запрос? Он просто раздает каждому клиенту абонемент с названием "Выходной". При этом не учитывается ни дата продажа ни срок окончания, ни, тем более, факт действительного приобретения такого абонемента. Какой практический смысл может иметь таблица с такими данными? Я могу предположить только один - диверсия с целью разрушения учета в организации.
13 окт 13, 15:30    [14962884]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
Bug69,

Спасибо огромное и Вам!!! В данный момент к сожалению не могу воспользоваться компьютером.Обязательно,первым делом,попробую описанные Вами процедуры, предварительно почитав о них....Ибо часто находя ответы на задаваемые вопросы в интернатах,я наталкиваюсь на всякого рода хранимки и процедуры.Но их изучение все откладывал,так как не много не допонимаю так сказать.Ваш пост,уважаемый Bug69, окончательно убедил меня в необходимости их изучения.Спасибо Вам ещё раз!!!

Так же хотел сказать,что способ предложенный другим участником этой ветки - работает, но я пожалуй все же попробую воспользоваться процедурами.
13 окт 13, 21:37    [14963633]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
Bug69
Member

Откуда: Москва, Чертаново
Сообщений: 229
Предложенный qwerty112 способ приводит к следующему: Из таблицы Clients выхватывается id (IDClient) первого попавшегося клиента, а из таблицы Abonement абонемент с названием (AbonName) "Выходной". Эти два значения и записываются в соответствующие поля таблицы Clients_Abonements. Возникает вопрос: насколько это соответствует Вашим требованиям?
Если в запросе убрать TOP 1, то в этом случае каждому имеющемуся клиенту будет сопоставлен абонемент с названием (AbonName) "Выходной".
Таким образом, предложенный qwerty112 способ будет корректно работать лишь в трех случаях:
1) У Вас в базе только один клиент
2) Из всех клиентов, имеющихся в базе, Вы активно работаете только с тем, кого возвращает данный запрос
3) Вам абсолютно безразлично какому клиенту приписать абонемент.

Во всех остальных случаях неадекватный результат гарантирован. Для работоспособности приведенного запроса нужна самая малость: в него следует добавить клиента.

USE [tempdb]
GO

IF EXISTS (SELECT * FROM [sys].[tables] AS [a] WHERE [a].[object_id] = OBJECT_ID(N'[dbo].[ClientsAbonements]')) DROP TABLE [dbo].[ClientsAbonements]
GO

IF EXISTS (SELECT * FROM [sys].[tables] AS [a] WHERE [a].[object_id] = OBJECT_ID(N'[dbo].[Clients]')) DROP TABLE [dbo].[Clients]
GO

IF EXISTS (SELECT * FROM [sys].[tables] AS [a] WHERE [a].[object_id] = OBJECT_ID(N'[dbo].[Abonements]')) DROP TABLE [dbo].[Abonements]
GO

CREATE TABLE [dbo].[Abonements]
(
	[idAbon] int IDENTITY(1, 1) NOT NULL
	, [abonName] varchar(50) NOT NULL
	, [abonPrice] money NOT NULL
	, CONSTRAINT [PK_Abonement] PRIMARY KEY ([idAbon])
	, CONSTRAINT [UQ_Abonement_abonName] UNIQUE ([abonName]) -- Хорошо бы сделать это поле уникальным, иначе у Вас расплодятся абонементы с одинаковыми названиями
	, CONSTRAINT [CK_Abonement_abonName] CHECK (LTRIM(RTRIM([abonName])) <> '') -- Хорошо бы убедится, что название абонемента не пустая строка
	, CONSTRAINT [CK_Abonement_abonPrice] CHECK ([abonPrice] > 0) -- Исключаем отрицательные и нулевые цены на абонементы
)
GO

CREATE TABLE [dbo].[Clients]
(
	[idClient] int IDENTITY(1, 1) NOT NULL
	, [name] varchar(50) NOT NULL
	, [surname] varchar(50) NOT NULL
	, [phone] varchar(50) NULL
	, [birth] date NULL
	, [photo] image NULL
	, [balance] money NOT NULL
	, CONSTRAINT [PK_Clients] PRIMARY KEY CLUSTERED ([idClient])
	, CONSTRAINT [UQ_Clients_name_surname] UNIQUE ([name], [surname]) -- Делаем комбинацию полей [name] и [surname] уникальной
	, CONSTRAINT [CK_Clients_name] CHECK (LTRIM(RTRIM([name])) <> '') -- Исключаем пустые строки в качестве имени
	, CONSTRAINT [CK_Clients_surname] CHECK (LTRIM(RTRIM([surname])) <> '') -- Исключаем пустые строки в качестве фамилии
)
GO

CREATE TABLE [dbo].[ClientsAbonements]
(
	[idClient] int NOT NULL
	, [idAbon] int NOT NULL
	, [saleDate] datetime NOT NULL
	, [validFrom] datetime NOT NULL
	, [expiredDate] datetime NOT NULL
	, CONSTRAINT [FC_ClientsAbonements_Abonements] FOREIGN KEY ([idAbon]) REFERENCES [dbo].[Abonements] ([idAbon]) -- Связь с таблицей Abonements
	, CONSTRAINT [FC_ClientsAbonements_Clients] FOREIGN KEY ([idClient]) REFERENCES [dbo].[Clients] ([idClient]) -- Связь с таблицей Clients
)
GO

INSERT INTO [dbo].[Abonements] -- Заполняем таблицу Abonements данными
SELECT 'Будни' AS [abonName], 200 AS [abonPrice] UNION
SELECT 'Выходные' AS [abonName], 100 AS [abonPrice] UNION
SELECT 'Все дни' AS [abonName], 300 AS [abonPrice]
GO

INSERT INTO [dbo].[Clients] -- Заполняем таблицу Clients данными
SELECT 'Иван' AS [name], 'Иванов' AS [surname], NULL AS [phone], NULL AS [birth], NULL AS [photo], 1000 AS [balance] UNION
SELECT 'Петр' AS [name], 'Петров' AS [surname], NULL AS [phone], NULL AS [birth], NULL AS [photo], 1000 AS [balance] UNION
SELECT 'Сидор' AS [name], 'Сидоров' AS [surname], NULL AS [phone], NULL AS [birth], NULL AS [photo], 1000 AS [balance]
GO

/*
=== Все готово для проверки ===
*/

INSERT INTO [dbo].[ClientsAbonements] ([idClient], [idAbon], [saleDate], [validFrom], [expiredDate]) -- Выполняем запрос по рецепту qwerty112
SELECT TOP 1
	[a].[idClient]
	, [b].[idAbon]
	, '20130925' AS [saleDate]
	, '20131001' AS [validFrom]
	, '20131101' AS [expiredDate]
FROM
	[dbo].[Clients] AS [a] 
	CROSS JOIN [dbo].[Abonements] AS [b]
WHERE
	[b].[abonName] = 'Выходные'
GO

-- Проверяем результат
SELECT
	[a].[idClient]
	, [a].[idAbon]
	, [c].[name]
	, [c].[surname]
	, [b].[abonName]
FROM
	[dbo].[ClientsAbonements] AS [a]
	LEFT OUTER JOIN [dbo].[Abonements] AS [b] ON [b].[idAbon] = [a].[idAbon]
	LEFT OUTER JOIN [dbo].[Clients] AS [c] ON [c].[idClient] = [a].[idClient]

-- Абонемент получил почему-то Иванов, хотя выдать его хотели Сидорову (допустим)
GO

DELETE FROM [dbo].[ClientsAbonements] -- Очищаем неудачно заполненую таблицу
GO

-- Немного модифицируем запрос
INSERT INTO [dbo].[ClientsAbonements] ([idClient], [idAbon], [saleDate], [validFrom], [expiredDate])
SELECT TOP 1
	[a].[idClient]
	, [b].[idAbon]
	, '20130925' AS [saleDate]
	, '20131001' AS [validFrom]
	, '20131101' AS [expiredDate]
FROM
	[dbo].[Clients] AS [a] 
	CROSS JOIN [dbo].[Abonements] AS [b]
WHERE
	[b].[abonName] = 'Выходные'
	AND [a].[surname] = 'Сидоров' -- Это и есть модификация
	AND [a].[name] = 'Сидор'
GO

-- Снова проверяем результат
SELECT
	[a].[idClient]
	, [a].[idAbon]
	, [c].[name]
	, [c].[surname]
	, [b].[abonName]
FROM
	[dbo].[ClientsAbonements] AS [a]
	LEFT OUTER JOIN [dbo].[Abonements] AS [b] ON [b].[idAbon] = [a].[idAbon]
	LEFT OUTER JOIN [dbo].[Clients] AS [c] ON [c].[idClient] = [a].[idClient]

-- Теперь мы получили то, что хотели, но...
-- ... мы убеждаемся, что в исходной форме, без однозначного указания клиента данный запрос не пригоден для работы.
GO

/*
Все-таки хочется быть уверенным, что мы не продаем один и тот же абонемент одному и тому же лицу многократно.
Что что мы не продаем абонемент на перекрывающиеся периоды

Проверять все это следует в хранимых процедурах, либо в триггерах

Да и сами таблицы не помешает подретушировать
*/
14 окт 13, 00:35    [14964232]     Ответить | Цитировать Сообщить модератору
 Re: Insert из 2-х не связанных таблиц в одну  [new]
libeadier
Member

Откуда:
Сообщений: 15
Bug69,
А я все проверки хотел выполнять средствами delphi
А оказывается все это возможно и в SQL...
Надо читать читать и читать
14 окт 13, 07:39    [14964525]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить