Как бы я сделал это с SQL Server? - PullRequest
2 голосов
/ 14 сентября 2011

У меня две таблицы пользователей и адрес

схема таблицы пользователей

 user_id
 name
 address_id
 sent

схема таблицы адресов

 address_id
 create_date
 location
 user_id

У меня есть этот запрос, который возвращает 16 строк

select * from users where sent = 1;

но все address_id все NULL, потому что они еще не были созданы

Итак, мне нужно создать 16 строк в таблице адресов по одной для каждого пользователя с user_id пользователя, а затем установить address_id в таблице пользователей этого адреса

Пока я могу оставить поле местоположения пустым. Все, что мне нужно сделать, это установить для create_date значение CURRENT_DATE

Есть ли способ сделать это в одном запросе?

Ответы [ 4 ]

2 голосов
/ 14 сентября 2011

Не совсем уверен, что вы имеете в виду, но это должно, по крайней мере, указать вам правильное направление

Begin Try
    Begin Transaction

        Update Users
        Set Users.address = Address.address, create_date = GetDate()
        From Addresses
            Inner Join Users On Addresses.userid = Users.userid

    Commit Transaction
End Try
Begin Catch
    Rollback Transaction
End Catch

Это должно быть что-то вроде этого.Есть несколько способов решить проблему, так что повеселитесь и, надеюсь, это помогло.Для тестирования напишите два Select * From Users оператора, один до и один после.Также измените Commit Transaction на Rollback Transaction, чтобы вам не пришлось беспокоиться об ошибке.

Просто перечитайте вопрос: да, вы не можете сделать это за один раз, просто замените выражение Update на

Insert Into Addresses (address_id, create_date, location, user_id)
Values ('@ddr355_1d', GetDate(), '1234theLocation', 123478)

, и вам придется сделать это для каждого из них, но это должно быть легко, только с 16 записями в таблице User.Возможно, вы захотите изучить написание хранимой процедуры, если планируете добавить больше в таблицу.Что-то вроде этого

Create Procedure [dbo].[AddressesInsertData]
(
    @Address Int,
    @Location varchar(100),
    @UserId Int
)
As
Begin Try
    Begin Transaction

        Insert Into Addresses (address_id, create_date, location, user_id)
        Values (@Address, GetDate(), @Location, @UserId)

    Commit Transaction
End Try
Begin Catch
    Rollback Transaction
End Catch

Базовая структура хранимой процедуры.Я бы добавил туда if not exists, который обновит вместо вставки, но этого должно быть достаточно, чтобы вы начали.Надеюсь, эти примеры помогут вам кое-что прояснить и помочь вам.

2 голосов
/ 14 сентября 2011

Попробуйте это:

declare @user table(user_id [int] IDENTITY(1,1), name varchar(25), address_id int, sent int)
declare @address table(address_id [int] IDENTITY(1,1) NOT NULL, create_date datetime default getdate(), location varchar(100), user_id int)
declare @t table(user_id int, address_id int)

insert @user (name) values('you')
insert @user (name) values('someone else')


begin Transaction 

insert @address (user_id) 
output inserted.user_id, inserted.address_id
into @t
select user_id from @user u 
where not exists (select 1 from @address where u.user_id = user_id)

update u 
set u.address_id = t.address_id
from @user u
join @t t
on u.user_id = t.user_id

commit transaction 

select * from @user
select * from @address
1 голос
/ 14 сентября 2011

Вы не можете сделать это в ОДНОМ утверждении, вы можете сделать это в одной транзакции. Посмотреть этот похожий вопрос

0 голосов
/ 14 сентября 2011

Существуют практические правила разработки, согласно которым таблица моделирует ЛИБО сущность / класс ИЛИ отношения между сущностями / классами, но не оба.

Поэтому я предлагаю вам удалить столбец address_id из таблицы пользователей, удалить user_id из таблицы адресов и создать третью таблицу, содержащую как user_id, так и address_id, чтобы смоделировать отношения между пользователями и их адресами. , Это также избавит вас от необходимости иметь пустые столбцы.

...