2016-06-22 3 views
3

У меня есть две таблицы; они соединены подробно отношений на имя столбца с помощью Delphi Ado ссылкиНеоднозначное название столбца в выражении Sql

первой таблицы имеет кучу данных и fileref в качестве ключа 1, второй таблицы строк данных и fileref в качестве ключа 2

1-й таблицы имеет другую информацию, но одно значение fileref, второй таблицы провести много значений fileref, но разные счета

Таблица 1: идентификатора, fileref, 1, 2, 3, 4, 5, accno, 7, 8, 9 и т.д., и т.д. ...

таблица 2: ID, fileref, accno

SELECT * FROM vtindex a 
    JOIN vi_accno b 
    ON b.fileref = a.FileRef 
    WHERE (a.AccNo like '%123456789%') or (b.accno like '%123456789%') 

Выше запрос, где я получаю неоднозначного ошибку

идея заключается в том, что если я не найти accno столовое 1 он должен попытаться найти его в таблице 2

надеюсь, что это делает смысл и что wierd в том, что если я запускаю запрос внутри MSSMS, запрос возвращает результаты без ошибок

+2

изменить его для выбора *, б * –

+0

@RichBenner не работает m8 – Troz

+0

Я только что отправил в ответ, посмотреть и увидеть если он решает его. –

ответ

5

Вам нужно будет объявить свои колонки, что-то вроде этого;

SELECT 
    a.ID A_ID 
    ,a.fileref A_fileref 
    ,a.Field1 A_Field1 
    ,a.Field2 A_Field2 
    ,a.accno A_Accno 
    ,b.id B_ID 
    ,b.fileref B_fileref 
    ,b.accno B_accno 
FROM vtindex a 
JOIN vi_accno b 
    ON a.fileref = b.fileref 
WHERE a.AccNo like '%123456789%' 
    OR b.accno like '%123456789%' 

Если вы хотите только объявить, тогда сделайте это;

SELECT 
    a.* 
    ,b.id B_ID 
    ,b.fileref B_fileref 
    ,b.accno B_accno 
FROM vtindex a 
JOIN vi_accno b 
    ON a.fileref = b.fileref 
WHERE a.AccNo like '%123456789%' 
    OR b.accno like '%123456789%' 

Ваш вопрос в том, что вы используете поля как id, fileref и accno больше, чем один раз (из каждой таблицы) и имена конфликтующих. Если вы измените имена в своей таблице, в которых есть только три записи, вы можете уйти, оставив таблицу как есть.

+0

Это решило мою проблему, я переименовал поля во 2-й таблице и побежал с использованием этого запроса: SELECT a. *, b. * FROM vtindex a JOIN vi_accnot b ON b.vifileref = a.FileRef WHERE (a.AccNo like ' '%' + edit1.text + '%' ') или (b.viaccno like' '%' + edit1.Text + '%' ') – Troz

+0

так infact все помогли в направлении, на которое я получил ответ, так спасибо ВСЕ – Troz

+0

просто чтобы было ясно, что он ссылается на «Если вы измените имена на своей таблице, которые имеют только 3 записи, тогда вы можете уйти, оставив таблицу как есть». был ответ im кликнуть на ... – Troz

2

Просто попробуйте заменить * на явные имена столбцов и определить уникальные псевдонимы для каждого столбца. Это позволит устранить ошибку неоднозначности. Ниже приведен пример:

Обновлено:

SELECT a.*,b.Id as b_Id, b.Fileref as b_Fileref, b.accno as b_accno FROM vtindex a 
JOIN vi_accno b 
ON b.fileref = a.FileRef 
WHERE (a.AccNo like '%123456789%') or (b.accno like '%123456789%') 

Как @Joe C прокомментировал тоже, мы считаем, что вам не нужно посылать FileRef и b.Id столбцы внутри vi_accno к выходу, если наше предположение верно, то вы можете удалить их из вашей Выберите и упростить его следующим образом:

SELECT a.*, b.accno as b_accno FROM vtindex a 
JOIN vi_accno b 
ON b.fileref = a.FileRef 
WHERE (a.AccNo like '%123456789%') or (b.accno like '%123456789%') 
+0

yikes thats alot ссылок на колонки, разве нет более простого способа – Troz

+0

Есть бесплатные инструменты, которые делают это проще. Для SSMS я иногда использую Apex Sql Complete для автоматического создания списка выбора. –

+0

@Troz вы можете использовать сторонние инструменты, такие как «Apex» или «RedGate SQL Toolbelt». Или вы можете выбрать свой запрос, затем щелкните его правой кнопкой мыши и выберите «Запросить дизайн в редакторе».Эти параметры помогут вам управлять столбцами и их псевдонимами. –

1

Try это,

SELECT a.*,b.* FROM vtindex a 
    JOIN vi_accno b 
    ON b.fileref = a.FileRef 
    WHERE (a.AccNo like '%123456789%') or (b.accno like '%123456789%') 
+0

Это даст ту же ошибку, что и accno. как в a, так и в b. –

+0

Просто скопируйте и вставьте здесь ошибку. – DineshDB

+0

это не работает «префикс столбца« a »не совпадает с именем таблицы или псевдонимом, используемым в запросе« – Troz

2

У вас одинаковое имя столбца в обеих таблицах, поэтому используйте * тянет оба и конфликты имен. В SSMS вам разрешено это делать, поскольку вы просматриваете только результаты на экране, но как только вы отправляете данные адресату, который ожидает, что имена столбцов будут уникальными, вы получите сообщение об ошибке. Вам нужно будет явно указывать нужные столбцы в списке выбора.

Кроме того, исходя из вашего вопроса, я считаю, что вы захотите использовать coalesce (b.accno, a.accno). Это будет использовать accno от A только в том случае, если accno имеет значение null в B.

EDIT: Основываясь на комментариях, я считаю, что здесь приведен конкретный синтаксис, о котором я говорил. Обратите внимание, как coalesce решает проблему псевдонимов столбцов, имея только одно поле с именем, которое вы хотите.

SELECT ID, FileRef, cnum, Month, Type, Typei, 
     PropDesc, Coalesce(a.accno, b.accno) AccNo, person, client, idno,   
     Consultant, Memo, qclose, vtdate 
    FROM vtindex a 
    Join vi_accno b ON b.fileref = a.FileRef 
    WHERE (a.AccNo like '%123456789%') or (b.accno like '%123456789%') 
+0

неоднозначный идентификатор столбца id, а затем удалить id из sql, тогда он жалуется на неоднозначное имя столбца fileref? lol – Troz

1

У меня есть догадка, что ваша проблема возникает не столько из Sql, которую вы пытаетесь использовать, а в том, как вы пытаетесь ее построить, используя совершенно ненужный и подверженный ошибкам SQL.Add().

Приведенный ниже код выполняется правильно и без каких-либо претензий или ошибок в D7 против 2 таблиц в базе данных Sql Server 2014.

procedure TForm1.FormCreate(Sender: TObject); 
var 
    S : String; 
begin 
    // WARNING: Do not use this Sql in a live application 
    // There is a risk of Sql-Injection because the Sql includes the 
    // contents of Edit1.Text. Use a parameterised query instead! 
    S := 'select a.*, b.*'#13#10; 
    S := S + 'from TableA a join TableB b'#13#10; // the #13#10 can be replaced by a single space, 
    // if you prefer 
    S := S + 'on a.fileref = b.fileref'#13#10; 
    S := S + 'where (a.accno like ''%' + Edit1.Text + '%'')'#13#10; 
    S := S + 'or (b.accno like ''%' + Edit1.Text + '%'')'#13#10; 

    AdoQuery1.SQL.Text := S; 
    AdoQuery1.Open; 
end; 

Обратите внимание на использование одиночных кавычек по всему миру, без двойных кавычек.

ВАЖНО Построив Sql непосредственно из содержания управления TEdit делает ваше приложение отвечает на Sql Injection (https://en.wikipedia.org/wiki/SQL_injection). Вместо этого вы должны использовать параметризованный Sql. Тем не менее, сказал, что подпрограмма в AdoDB.Pas, которая анализирует Sql для создания параметров, TAdoCommand.ParseSql кажется, который должен быть разбит в D7-Delphi Seattle, потому что он не может распознать параметр, встроенный в `LIKE ' который включает строковое выражение. Путь к этому может заключаться в том, чтобы определить Хранимый Proc на сервере, который выполняет SQL с параметрами, предоставленными во время выполнения из приложения.

Итак, я предполагаю, что, поскольку вы используете SQL.Add(), на самом деле вы не строите Sql, о котором вы думаете. Я подозреваю, что ошибка, которую вы получаете, на самом деле пытается сказать вам, заключается в том, что Edit1.Text неоднозначен - в зависимости от вашего точного экземпляра Sql, возможно, Sql-парсер считает, что Edit1.Text - это имя столбца.

СКП DDL для TableA и TableB:..

CREATE TABLE [dbo].[TableA](
    [ID] [int] NOT NULL, 
    [FileRef] [int] NULL, 
    [AccNo] [varchar](32) NULL, 
PRIMARY KEY CLUSTERED 
(
    [ID] 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 

CREATE TABLE [dbo].[TableB](
    [ID] [int] NOT NULL, 
    [FileRef] [int] NULL, 
    [AccNo] [varchar](32) NULL, 
PRIMARY KEY CLUSTERED 
(
    [ID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
+0

Ничего плохого в SQL.Add, где OP говорит, что он это делает ?. С другой стороны, никогда не создавайте SQL, если вам это не нужно. Ваш образец кода подвержен SQL-инъекции, пожалуйста, отрегулируйте его (люди будут читать ваш ответ и копировать/вставлять, не думая). Всегда (и я имею в виду ВСЕГДА) используют параметры ... – whosrdaddy

+0

@whosrdaddy: Я отрегулирую ответ в моменте. Между тем, где? В комментарии OP к ответу DineshDB «точный код: form3.adoquery1.SQL.Add (« SELECT a. *, B. * FROM vtindex a »); form3.adoquery1.SQL.Add ('JOIN vi_accno b '); form3.adoquery1.SQL.Add (' ON a.fileref = b.FileRef '); form3.adoquery1.SQL.Add (' WHERE (a.AccNo like ''% '+ edit1.text +'% '') или (b.accno like ''% '+ edit1.Text +'% '') '); " – MartynA

+0

@whosrdaddy: Кстати, я согласен с тем, что в принципе нет ничего неправильного * с SQL.Add(), это просто кажется частое использование в SO qs для ошибочного SQL. – MartynA

Смежные вопросы