2012-07-11 13 views
5

Właśnie sobie sprawę, że zostały przechwytywanie niewłaściwych danych dla jednej kolumny w mojej tabeli. Rozwiązałem problem, jednak dane, które zdobyłem do tej pory, są nieprawidłowe. NazwaJak zaktualizować dane kolumn przy użyciu innych tabel danych TSQL

Miejmy moje tabele TableIWantToCorrect i TableWithIDs

W TableIWantToCorrect, mam klucz obcy do TableWithIDs. To jest niepoprawne.

Jestem w stanie skorygować dane przez porównanie podciągu kolumny w TableIWantToCorrect z kolumną w TableWithIDs.

więc obecnie mam

TableIWantToCorrect

Name   ForeignKey 
123-abc-123  15 
456-def-456  15 
789-ghi-789  15 

TableWithIDs

CompareName id 
abc   1 
def   2 
ghi   3 

Więc chcę zaktualizować TableIWantToCorrect mieć prawidłową wartość ForeignKey gdy podciąg w Nazwa jest równa podciąganiu w Porównać nazwę. Położenie podciągu jest zawsze takie samo, więc mogę użyć metody Substring.

Moja próba:

Update TableIWantToCorrect 
SET ForeignKey = 
     (SELECT id 
     FROM TableWithIDs 
     WHERE UPPER(CompareName) = UPPER((SUBSTRING(TableIWantToCorrect.Name, 4, 3))) 

Rezultat:

Podkwerenda zwrócone więcej niż 1 wartość. Jest to niedozwolone, gdy podkwerenda następuje po, = =,! =, <, < =,>,> = lub gdy podzapytanie jest używane jako wyrażenie. Oświadczenie zostało wypowiedziane.

Wiem, że zrobiłem coś głupiego. Co ja tu zrobiłem niepoprawnie?

+1

swojej inline-zapytania jest zwrócenie więcej niż jeden wiersz stąd ten problem. Uruchomić tę kwerendę, aby dowiedzieć się, które z nich są powtarzane 'SELECT CompareName, count (1) \t OD TableWithIDs GROUP BY CompareName HAVING COUNT (1)> 1 \t ' – Chandu

+0

Czy nadal pojawia się błąd po zmianie podzapytanie do użyć "SELECT DISTINCT id'? Jeśli tak, istnieje wiele możliwych dopasowań i nie jest jednoznaczne, który z nich zastosować. –

+0

możliwy duplikat [UPDATE z SELECT przy użyciu SQL Server] (http://stackoverflow.com/questions/2334712/update-from-select-using-sql-server) –

Odpowiedz

13

Błąd jest taki, że podkwerenda zwraca więcej niż jeden rekord dla UPDATE. Aby rozwiązać ten problem, można to zrobić za pomocą JOIN z UPDATE

UPDATE t1 
SET ForeignKey = t2.id 
FROM TableIWantToCorrect t1 
INNER JOIN TableWithIDs t2 
    ON UPPER(t2.CompareName) = UPPER(SUBSTRING(t1.Name, 4, 3)) 
+1

Wiem, że jest to pytanie SQL Server, ale jeśli chcesz tego dokonać, użyj MySQL: http://stackoverflow.com/a/11709090/403264 – JonRed

2
Update TableIWantToCorrect 
SET ForeignKey = s.id 
FROM TableIWantToCorrect , TableWithIDs as s 
WHERE UPPER(s.CompareName) = UPPER((SUBSTRING(TableIWantToCorrect.Name, 4, 3)) 
+1

Zawsze możesz powiedzieć, kto pracuje w Oracle, nigdy nie używają polecenie łączenia. ;) – Limey

+1

Niestety przechodzę pomiędzy serwerem Oracle i Sql, więc trochę czasu mi się zdezorientuje ..!niemniej jednak dają ten sam wynik, ale nadal należy preferować .http: //stackoverflow.com/questions/1018822/inner-join-on-vs-where-clause – praveen

+1

Miałem 10 lat w Oracle i nienawidziłem dołącz oświadczenie! Z jakiegoś powodu zawsze trudno mi było czytać, ale po latach na serwerze SQL widziałem błędy moich sposobów i zawsze korzystałem z połączeń. – Limey

-1
--CREATE FUNCTION dbo.ufn_FindReports 
--(@InEmpID INTEGER) 
--RETURNS @retFindReports TABLE 
--(
-- EmployeeID int primary key NOT NULL, 
-- FirstName nvarchar(255) NOT NULL, 
-- LastName nvarchar(255) NOT NULL, 
-- JobTitle nvarchar(50) NOT NULL 

--) 
----Returns a result set that lists all the employees who report to the 
----specific employee directly or indirectly.*/ 
--AS 
--BEGIN 
--WITH EMP_cte(EmployeeID, OrganizationNode, FirstName, LastName, JobTitle, RecursionLevel) -- CTE name and columns 
-- AS (
--  SELECT e.EmployeeID, e.ManagerID, p.FirstName, p.LastName, P.JobTitle, 0 -- Get the initial list of Employees for Manager n 
--  FROM HumanResources.Employee e 
--INNER JOIN Person.Person p 
--ON p.Employeeid = e.EmployeeID 
--  WHERE e.EmployeeID = @InEmpID 
--  UNION ALL 
--  SELECT e.EmployeeID, e.ManagerID, p.FirstName, p.LastName, P.JobTitle, RecursionLevel + 1 -- Join recursive member to anchor 
--  FROM HumanResources.Employee e 
--   INNER JOIN EMP_cte 
--   ON e.ORGANIZATIONNODE.GetAncestor(1) = EMP_cte.OrganizationNode 
--INNER JOIN Person.Person p 
--ON p.Employeeid= e.EmployeeID 
--  ) 
---- copy the required columns to the result of the function 
-- INSERT @retFindReports 
-- SELECT EmployeeID, FirstName, LastName, JobTitle, RecursionLevel 
-- FROM EMP_cte 
-- RETURN 
--END; 
--GO 

> 
Powiązane problemy