SQL table names with spaces - sql-server

I have a table name with spaces between say like 'Orders Details'.
I want to use that table in stored procedures with joins.I have tried using alias names,[],`` in queries but nothing seems to be working.Can anybody help me on this error!

Do not use order as a column alias. It is a SQL keyword. I would just use o:
select o.*, od.*
from orders o join
order_details od
on o.orderid = od.orderid
where year(o.orderdate) = #orderyear;
Notes:
Your JOIN condition is on ProductId. However, that is highly suspicious. Usually such joins are on the order id. In fact, ProductId doesn't belong in Orders (usually) if there is a detail table.
Do not define your tables with spaces in the name. That just makes it hard to reference the names.
orderdate does not seem to be defined, because it has a red underline.
I don't recommend select *. For one thing, you will have duplicate column names. More importantly, you want to be explicit about what this code returns, particularly in a stored function or procedure.

Related

Microsoft SQL -- struggles with CROSS JOIN

So i have to do a cartesian product (or CROSS JOIN) between two tables. One problem is that both tables have a column with the name 'itemname'. My current case looks as follows:
select *
into #cartesian_temp
from xsale CROSS JOIN xitem
delete from #cartesian_temp where deptname='books' and itemcolor='bamboo'
select * from #cartesian_temp
so the error I get is:
Column names in each table must be unique. Column name 'itemname' in table '#cartesian_temp' is specified more than once
Anyone that can help me with my problem?
you can add alias for the columns like below.
select XS.itemname as saleitemname , XI.itemname as saleitemname2
into #cartesian_temp
from xsale XS CROSS JOIN xitem XI
This is one of the reasons why seasoned SQL pro's will ALWAYS advocate to give Tables an alias and to ALWAYS fully qualify every column name by using the alias. It's not just a cross join problem
Avoid this:
SELECT *
FROM
person
INNER JOIN
address
ON addressid = address.id -- Person.addressid
Sure, it'll work as long as the column names are all unique (it'll probably cause issues even now because person will have an I'd column and so will address) but it might stop working at any point in future if someone adds columns to either table with names that clash
Prefer this:
SELECT p.id as personid, a.id as addressid, p.name, a.zipcode
FROM
person p
INNER JOIN
address a
ON p.addressid = a.id
This is fully aliased (both tables have an alias) and we haven't used select *; weve fully qualified every column with a prefix using the table alias and we've aliased columns that have the same named (the ID columns) in each table so we can tel them apart. No one can add any columns to the db and cause this query to stop working
Aliasing Tables helps in another way; it lets us use the same table twice in a query. Suppose a person had a work address and a home address:
SELECT ...
FROM
person p
INNER JOIN
address awork
ON p.workaddressid = awork.id
INNER JOIN
address ahome
ON p.homeaddressid = ahome.id
This is impossible without aliasing. Always give aliases a sensible name (not a1, a2)
For your case, go like:
SELECT xs.itemname as xsitemname, xi.itemname as xiitemname, ...
FROM
xsale xs
CROSS JOIN
xitem xi
WHERE
xi.itemcolor = 'green'
This will be every green item crossed with every sale item

Determine Tables Referenced By Letters In Stored Procedure

I have a stored procedure that references a few tables. However, it refers to the tables with letters.
So let's say a column called Name is from the table Users, then the stored procedure may call the column name U.Users.
My question is, how do I get a list of all such mappings i.e all the letters that map to a table?
you are referring to table aliases, each distinct query can have their own "mapping". These alias values are not specific to stored procedures. Here is an example:
select
a.col1, a.col2
FROM YourTable1 a
select
b.col1, b.col2
from YourTable2 a
inner join YourTable1 b on a.col1=b.col2
YourTable1.col1 and YourTable1.col2 are returned in both of the above queries, although they have the "a" alias in the first query and "b" alias in the second query. See this Using Table Aliases.
In examples like above, people often use a table alias because is is quicker to write a.col1 than YourTable.col1. There is no way for anyone to know the aliases used in your stored procedure, you need to figure that out, look at these examples to help:
FROM YourTable a
-- ^table ^alias
FROM YourTable AS a
-- ^table ^alias
FROM YourTable1 a
INNER JOIN YourTable2 b ON a.col1=b.col1
-- ^table ^alias
FROM YourTable1 AS a
INNER JOIN YourTable2 AS b ON a.col1=b.col1
-- ^table ^alias
Each statement assigns its own aliases for the tables it uses, if at all. The same table used in different statements could be aliased differently (or not aliased). There cannot possibly be a single place to look up every table alias or a simple method to recover them from all the statements in your stored procedure or function or view etc.

Search in multiple tables with Full-Text

I'm trying to make a detailed search with asp and SQL Server Full-text.
When a keyword submitted, I need to search in multiple tables. For example,
Table - Members
member_id
contact_name
Table - Education
member_id
school_name
My query;
select mem.member_id, mem.contact_name, edu.member_id, edu.school_name from Members mem FULL OUTER JOIN Education edu on edu.member_id=mem.member_id where CONTAINS (mem.contact_name, '""*"&keyword&"*""') or CONTAINS (edu.school_name, '""*"&keyword&"*""') order by mem.member_id desc;
This query works but it takes really long time to execute.
Image that the keyword is Phill; If mem.contact_name matches then list it, or if edu.school_name matches, list the ones whose education match the keyword.
I hope I could explain well :) Sorry for my english though.
Perhaps try an indexed view containing the merged dataset- you can add the fulltext index there instead of the individual tables, and it's further extensible to as many tables as you need down the line. Only trick, of course, is the space...
This is what I would do for my multi table full text search.
Not exact but it will give basic idea. the key thing is to give table vise contain with OR condition.
DECLARE #SearchTerm NVARCHAR(250)
SET #SearchTerm = '"Texas*"'
SELECT * FROM table1
JOIN table2 on table1.Id = table2.FKID
WHERE (
(#SearchTerm = '""') OR
CONTAINS((table1.column1, table1.column2, table1.column3), #SearchTerm) OR
CONTAINS((table2.column1, table2.column2), #SearchTerm)
)
Couple of points I don't understand that will be affecting your speed.
Do you really need a full outer join? That's killing you. It looks like these tables are one to one. In that case can't you make it an inner join?
Can't you pass a column list to contains like so:
SELECT mem.member_id,
mem.contact_name,
edu.member_id,
edu.school_name
FROM members mem
INNER JOIN education edu ON edu.member_id = mem.member_id
WHERE Contains((mem.contact_name,edu.school_name),'*keyword*')
ORDER BY mem.member_id DESC
Further info about contains.

Getting repetitive column names by adding a prefix to the repeated column name in SQL Server 2005

How can I write a stored procedure in SQL Server 2005 so that i can display the repeated column names by having a prefix added to it?
Example: If I have 'Others' as the column name belonging to a multiple categories mapped to another table having columns as 'MyColumn','YourColumn'. I need to join these two tables so that my output should be 'M_Others' and 'Y_Others'. I can use a case but I am not sure of any other repeated columns in the table. How to write that dynamically to know the repetitions ?
Thanks In Advance
You should use aliases in the projection of the query: (bogus example, showing the usage)
SELECT c.CustomerID AS Customers_CustomerID, o.CustomerID AS Orders_CustomerID
FROM Customers c INNER JOIN Orders o ON c.CustomerID = o.CustomerID
You can't dynamically change the column names without using dynamic SQL.
You have to explicitly alias them. There is no way to change "A_Others" or "B_Others" in this query:
SELECT
A.Others AS A_Others,
B.Others AS B_Others
FROM
TableA A
JOIN
TableB B ON A.KeyCol = B.KeyCol
If the repeated columns contain the same data (i.e. they are the join fields), you should not be sending both in the query anyway as this is a poor practice and is wasteful of both server and network resources. You should not use select * in queries on production especially if there are joins. If you are properly writing SQL code, you would alias as you go along when there are two columns with the same name that mean different things (for instance if you joined twice to the person table, once to get the doctor name and once to get the patient name). Doing this dynamically from system tables would not only be inefficient but could end up giving you a big security hole depending on how badly you wrote the code. You want to save five minutes or less in development by permanently affecting performance for every user and possibly negatively impacing data security. This is what database people refer to as a bad thing.
select n.id_pk,
(case when groupcount.n_count > 1 then substring(m.name, 1, 1) + '_' + n.name
else n.name end)
from test_table1 m
left join test_table2 n on m.id_pk = n.id_fk
left join (select name, count(name) as n_count
from test_table2 group by name)
groupcount on n.name = groupcount.name

Using Full-Text Search in SQL Server 2008 across multiple tables, columns

I need to search across multiple columns from two tables in my database using Full-Text Search. The two tables in question have the relevant columns full-text indexed.
The reason I'm opting for Full-text search:
1. To be able to search accented words easily (cafè)
2. To be able to rank according to word proximity, etc.
3. "Did you mean XXX?" functionality
Here is a dummy table structure, to illustrate the challenge:
Table Book
BookID
Name (Full-text indexed)
Notes (Full-text indexed)
Table Shelf
ShelfID
BookID
Table ShelfAuthor
AuthorID
ShelfID
Table Author
AuthorID
Name (Full-text indexed)
I need to search across Book Name, Book Notes and Author Name.
I know of two ways to accomplish this:
Using a Full-text Indexed View: This would have been my preferred method, but I can't do this because for a view to be full-text indexed, it needs to be schemabound, not have any outer joins, have a unique index. The view I will need to get my data does not satisfy these constraints (it contains many other joined tables I need to get data from).
Using joins in a stored procedure: The problem with this approach is that I need to have the results sorted by rank. If I am making multiple joins across the tables, SQL Server won't search across multiple fields by default. I can combine two individual CONTAINS queries on the two linked tables, but I don't know of a way to extract the combined rank from the two search queries. For example, if I search for 'Arthur', the results of both the Book query and the Author query should be taken into account and weighted accordingly.
Using FREETEXTTABLE, you just need to design some algorithm to calculate the merged rank on each joined table result. The example below skews the result towards hits from the book table.
SELECT b.Name, a.Name, bkt.[Rank] + akt.[Rank]/2 AS [Rank]
FROM Book b
INNER JOIN Author a ON b.AuthorID = a.AuthorID
INNER JOIN FREETEXTTABLE(Book, Name, #criteria) bkt ON b.ContentID = bkt.[Key]
LEFT JOIN FREETEXTTABLE(Author, Name, #criteria) akt ON a.AuthorID = akt.[Key]
ORDER BY [Rank] DESC
Note that I simplified your schema for this example.
I had the same problem as you but it actually involved 10 tables (a Users table and several others for information)
I did my first query using FREETEXT in the WHERE clause for each table but the query was taking far too long.
I then saw several replies about using FREETEXTTABLE instead and checking for not nulls values in the key column for each table, but that took also to long to execute.
I fixed it by using a combination of FREETEXTTABLE and UNION selects:
SELECT Users.* FROM Users INNER JOIN
(SELECT Users.UserId FROM Users INNER JOIN FREETEXTTABLE(Users, (column1, column2), #variableWithSearchTerm) UsersFT ON Users.UserId = UsersFT.key
UNION
SELECT Table1.UserId FROM Table1 INNER JOIN FREETEXTTABLE(Table1, TextColumn, #variableWithSearchTerm) Table1FT ON Table1.UserId = Table1FT.key
UNION
SELECT Table2.UserId FROM Table2 INNER JOIN FREETEXTTABLE(Table2, TextColumn, #variableWithSearchTerm) Table2FT ON Table2.UserId = Table2FT.key
... --same for all tables
) fts ON Users.UserId = fts.UserId
This proved to be incredibly much faster.
I hope it helps.
I don't think the accepted answer will solve the problem. If you try to find all the books from a certain author and, therefore, use the author's name (or part of it) as the search criteria, the only books returned by the query will be those which have the search criteria in its own name.
The only way I see around this problem is to replicate the Author's columns that you wish to search by in the Book table and index those columns (or column since it would probably be smart to store the author's relevant information in an XML column in the Book table).
FWIW, in a similar situation our DBA created DML triggers to maintain a dedicated full-text search table. It was not possible to use a materialized view because of its many restrictions.
I would use a stored procedure. The full text method or whatever returns a rank which you can sort by. I am not sure how they will be weighted against eachother, but I'm sure you could tinker for awhile and figure it out. For example:
Select SearchResults.key, SearchResults.rank From FREETEXTTABLE(myColumn, *, #searchString) as SearchResults Order By SearchResults.rank Desc
This answer is well overdue, but one way to do this if you cannot modify primary tables is to create a new table with the search parameters added to one column.
Then create a full text index on that column and query that column.
Example
SELECT
FT_TBL.[EANHotelID] AS HotelID,
ISNULL(FT_TBL.[Name],'-') AS HotelName,
ISNULL(FT_TBL.[Address1],'-') AS HotelAddress,
ISNULL(FT_TBL.[City],'-') AS HotelCity,
ISNULL(FT_TBL.[StateProvince],'-') AS HotelCountyState,
ISNULL(FT_TBL.[PostalCode],'-') AS HotelPostZipCode,
ISNULL(FT_TBL.[Latitude],0.00) AS HotelLatitude,
ISNULL(FT_TBL.[Longitude],0.00) AS HotelLongitude,
ISNULL(FT_TBL.[CheckInTime],'-') AS HotelCheckinTime,
ISNULL(FT_TBL.[CheckOutTime],'-') AS HotelCheckOutTime,
ISNULL(b.[CountryName],'-') AS HotelCountry,
ISNULL(c.PropertyDescription,'-') AS HotelDescription,
KEY_TBL.RANK
FROM [EAN].[dbo].[tblactivepropertylist] AS FT_TBL INNER JOIN
CONTAINSTABLE ([EAN].[dbo].[tblEanFullTextSearch], FullTextSearchColumn, #s)
AS KEY_TBL
ON FT_TBL.EANHotelID = KEY_TBL.[KEY]
INNER JOIN [EAN].[dbo].[tblCountrylist] b
ON FT_TBL.Country = b.CountryCode
INNER JOIN [EAN].[dbo].[tblPropertyDescriptionList] c
ON FT_TBL.[EANHotelID] = c.EANHotelID
In the code above [EAN].[dbo].[tblEanFullTextSearch], FullTextSearchColumn is the new table and column with the fields added, you can now do a query on the new table with joins to the table you want to display the data from.
Hope this helps

Resources