Query Field Names Of All Tables - sql-server-2008

Here's a fun one.
Occasionally we may want to find the tables consisting of certain fields, this is because our schema's are so large, and our affiliation with external entities for database definitions causes a bit of confusion when composing certain queries.
Sometimes I need to know the answer to the question of: "What tables in database X contains the field name of Y?"
Querying schemas isn't my forté, and neither is finding search criteria to yield something mildly useful.
Cheers

I would use this query:
SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = 'ColumnName'

I use this:
select * from sys.tables
where object_id in
(
select object_id from sys.columns where [name] = 'FieldName'
)

Related

MySQL "exists" function in "where" clause

I would like to select a field only if the field exists on the table. If it does not exist, then I want to select a different field in the "where" clause.
The use case for this is that I have several similar tables, some of which have a "user_id" field and others do not, but rather than hard-coding all the tables that have this, I want to just check for the existence of the field, so that I can use the same sql for all. Those that do not have user_id use the "id" field instead for my application.
This code gives me the error
Unknown column 'user_id' in 'where clause'
for the table that does not have a user_id field.
I am using MySQL 5.7
select id from users
where
if (
exists( select 1 from information_schema.columns where table_name = 'users' and column_name = 'user_id' ),
user_id > 10,
id > 10);
I don't think you can achieve what you're looking to do in the way you're looking to do it.
The interpreter has no expectation that you might only want to use one of these fields, and it correctly points out that one of them is not valid for that query.
I think you'd have a far easier time having a common field name for everything you're searching on.
Consider creating views that provide all the columns of the base table and map the varying column as user_id.
e.g.
CREATE VIEW uniform_user
AS
SELECT
id,
id as user_id,
...
You can then exploit these views rather than the base tables and know that a user_id will definitely exist in each.
SELECT user_id FROM uniform_user
etc.

MySQL return full table.column names

If I have a query thus:
SELECT id, name, age FROM people;
I will get columns named id, name and age. Is there an option to specify "I want full table.column names in my result"? IE, ideally I'd run the above query and get the columns people.id, people.name and people.age.
If it makes a difference, the query is being run from PHP.
I do not wish to use SELECT id AS people.id (etc) as I have around 50 queries containing around 10-12 columns each. I wish to avoid manually rewriting all these queries.
The 'duplicate' question has no answer for my issue (nor it's original question as far as I can tell) other than "it's not possible".
You can use column aliases for that purpose.
SELECT id AS 'people.id', name AS 'people.name', age AS 'people.age' FROM people;
You can simply use as
SELECT id as `people.id`, name as `people.name`, age as `people.age` FROM people;
Try this.
Try this...concat your table name with column_name and get all the column from your table using information schema.......
SELECT group_concat('table1.',COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'db_name' AND TABLE_NAME = 'table1';
later on if you want you can store that result in variable and use them as per your requirement.
rather you can create a dynamic query using input table name and db_name and traverse them until your goal reach :-)
Use Alias
Basically aliases are created to make column names more readable.
Sql Aliases
Example :
SELECT id AS 'people.id', name AS 'people.name', age AS 'people.age' FROM people;

Subquery for fetching table name

I have a query like this :
SELECT * FROM (SELECT linktable FROM adm_linkedfields WHERE name = 'company') as cbo WHERE group='BEST'
Basically, the table name for the main query is fetched through the subquery.
I get an error that #1054 - Unknown column 'group' in 'where clause'
When I investigate (removing the where clause), I find that the query only returns the subquery result at all times.
Subquery table adm_linkedfields has structure id | name | linktable
Currently am using MySQL with PDO but the query should be compatible with major DBs (viz. Oracle, MSSQL, PgSQL and MySQL)
Update:
The subquery should return the name of the table for the main query. In this case it will return tbl_company
The table tbl_company for the main query has this structure :
id | name | group
Thanks in advance.
Dynamic SQL doesn't work like that, what you created is an inline-view, read up on that. What's more, you can't create a dynamic sql query that will work on every db. If you have a limited number of linktables you could try using left-joins or unions to select from all tables but if you don't have a good reason you don't want that.
Just select the tablename in one query and then make another one to access the right table (by creating the query string in php).
Here is an issue:
SELECT * FROM (SELECT linktable FROM adm_linkedfields WHERE name = 'company') as cbo
WHERE group='BEST';
You are selecting from DT which contains only one column "linktable", then you cant put any other column in where clause of outer block. Think in terms of blocks the outer select is refering a DT which contains only one column.
Your problem is similar when you try to do:
create table t1(x1 int);
select * from t1 where z1 = 7; //error
Your query is:
SELECT *
FROM (SELECT linktable
FROM adm_linkedfields
WHERE name = 'company'
) cbo
WHERE group='BEST'
First, if you are interested in cross-database compatibility, do not name columns or tables after SQL reserved words. group is a really, really bad name for a column.
Second, the from clause is returning a table containing a list of names (of tables, but that is irrelevant). There is no column called group, so that is the problem you are having.
What can you do to fix this? A naive solution would be to run the subquery, run it, and use the resulting table name in a dynamic statement to execute the query you want.
The fundamental problem is your data structure. Having multiple tables with the same structure is generally a sign of a bad design. You basically have two choices.
One. If you have control over the database structure, put all the data in a single table, linktable for instance. This would have the information for all companies, and a column for group (or whatever you rename it). This solution is compatible across all databases. If you have lots and lots of data in the tables (think tens of millions of rows), then you might think about partitioning the data for performance reasons.
Two. If you don't have control over the data, create a view that concatenates all the tables together. Something like:
create view vw_linktable as
select 'table1' as which, t.* from table1 t union all
select 'table2', t.* from table2 t
This is also compatible across all databases.

mySQL convert integer to text in SELECT query

I want to convert an integer to text in a mySQL select query. Here's what a table looks like:
Languages
--------
1,2,3
I want to convert each integer to a language (e.g., 1 => English, 2 => French, etc.)
I've been reading up on CONVERT and CAST functions in mySQL, but they mostly seem to focus on converting various data types to integers. And also I couldn't find anything that dealt with the specific way I'm storing the data (multiple numbers in one field).
How can I convert the integers to text in a mySQL query?
UPDATE
Here's my mySQL query:
SELECT u.id, ulp.userid, ulp.languages, ll.id, ll.language_detail
FROM users AS u
JOIN user_language_profile AS ulp ON (ulp.userid = u.id)
JOIN language_detail AS ll ON (ulp.languages = ll.id)
Use either:
MySQL's ELT() funtion:
SELECT
ELT(Languages
, 'English' -- 1
, 'French' -- 2
-- etc.
)
FROM table_name
A CASE expression:
SELECT
CASE Languages
WHEN 1 THEN 'English'
WHEN 2 THEN 'French'
-- etc.
END
FROM table_name
Although, if possible I would be tempted to either JOIN with a lookup table (as #Mr.TAMER says) or change the data type of the column to ENUM('English','French',...).
UPDATE
From your comments, it now seems that each field contains a set (perhaps even using the SET data type?) of languages and you want to replace the numeric values with strings?
First, read Bill Karwin's excellent answer to "Is storing a delimited list in a database column really that bad?".
In this case, I suggest you normalise your database a tad: create a new language-entity table wherein each record associates the PK of the entities in the existing table with a single language. Then you can use a SELECT query (joining on that new table) with GROUP_CONCAT aggregation to obtain the desired list of language names.
Without such normalisation, your only option is to do string-based search & replace (which would not be particularly efficient); for example:
SELECT CONCAT_WS(',',
IF(FIND_IN_SET('1', Languages), 'English', NULL),
IF(FIND_IN_SET('2', Languages), 'French' , NULL),
-- etc.
)
FROM table_name
Why don't you make a number-language table and, when SELECTing, get the language associated with that number that you selected.
This is better in case you want to add a new language. You will only insert it into the table instead of changing all the queries in your code, and also easier if others are using your code (they won't be happy debugging and editing all the queries).
From your other comments, are you saying that the languages field is a literal string embedded with commas?
From an SQL perspective, that's a pretty unworkable design. A variable number of languages should be stored in another table.
However, if you're stuck with what you've got, you might be able to construct a regexp replacement algorithm, but it seems terribly fragile, and I wouldn't recommend it. If you've got more than 9 languages, the following will be broken, and you would need the Regexp UDF, which introduces a bunch of complexity.
Assuming the simple case:
SELECT REPLACE(
REPLACE(
REPLACE(Languages, '1', 'English'),
'2', 'French'),
N, DESCRIPTION)
and so on. But I repeat: this is an awful data design. If it's possible to fix it to something like:
person person_lang language
========== ============ =========
person_id -----< person_id
... lang_id >----- lang_id
lang_desc
Then I strongly suggest you do so.

Select columns by numbers - SELECT [m:n] FROM table_name

I have a database with many columns and sometimes I need to select quite a few.
Selecting all columns would be too much data. So lets say that:
DESC table_name
gives ordered column names, for example (A,B,C,D,E,F,G,H,I,J....). Is it possible that instead:
SELECT C,D,E,F FROM table_name;
I do something like this:
SELECT [3:6] FROM table_name
I know it makes no difference in this example, but I need to select over 40 columns with long names.
No, you can't SELECT [3:6] FROM table_name What do you think this is, some kind of modern computer language with sequences and ranges as first class data types? :-) :-). This is SQL.
You can, as a commenter pointed out, fetch the names of the columns in the table and then programmatically generate your SQL queries. This is, of course, something a bunch of different data-access-object packages do automatically.