sql, database query - sql

could anyone tell me how to select particular column if i dont know the schema of table .Like if i want only the values in the second column of database table without knowing the column name. Is there a way to do that?

You should almost NEVER rely on column number in a table in any of your code (even though you CAN theoretically do so technically for certain database libraries in certain languages).
There are many reasons, one of the most important is that someone can always ALTER the table and insert a column in the beginning / middle, breaking your code completely.
A second reason is that column positions - even if you assume that the table never changes - make for absolutely UNREADABLE and therefore impossible to maintain code. Will you remember that column 13 was "last_name_3" 2 years from now?

Although I'd never recommend doing what you propose, assuming your RDBMS has implemented the SQL-92 INFORMATION_SCHEMA standard, you could get the column name and use it to build dynamic SQL.
SELECT c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c
WHERE c.TABLE_NAME = 'YourTable'
AND c.ORDINAL_POSITION = 2

Not sure what you wanted to do. And I sincerely expect you don't do what you're doing. But if you jsut wanted to know how to play with technicality. Here is an example to do it. There may be better ways.
mysql> desc test;
+-------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+-------+
| id | int(11) | YES | | NULL | |
| name | varchar(100) | YES | | NULL | |
+-------+--------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
mysql> select * from test;
+------+-------+
| id | name |
+------+-------+
| 1 | name1 |
| 2 | name2 |
| 3 | name3 |
| 4 | name4 |
+------+-------+
4 rows in set (0.00 sec)
mysql> select #colid:=column_name from information_schema.columns where table_schema='test' and table_name='test' and ordinal_position=2;
+---------------------+
| #colid:=column_name |
+---------------------+
| name |
+---------------------+
1 row in set (0.01 sec)
mysql> set #sqlstr:=concat('select ', #colid, ' from test');
Query OK, 0 rows affected (0.00 sec)
mysql> prepare sttmt from #sqlstr;
Query OK, 0 rows affected (0.00 sec)
Statement prepared
mysql> execute sttmt;
+-------+
| name |
+-------+
| name1 |
| name2 |
| name3 |
| name4 |
+-------+
4 rows in set (0.00 sec)
refer the last example here http://dev.mysql.com/doc/refman/5.0/en/user-variables.html
By the way, Google gives first link as perfect solution. Select statement with column number instead of column names

Can you do a select * from mytable to figure out what the column names are?
You could also try select * from information_schema.columns where table_name = 'mytable' if your database supports an information_schema view. There are other ways to figure out the names of columns. I would suggest just trying to figure out the name over any other possible workaround.

This could be done with SQL Server/.NET like this:
SqlCommand command =
new SqlCommand("SELECT * FROM TABLE", connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
string secondVal = reader[1].ToString();
}
I would take a hard look at why you need to do this in the first place though. Seems fishy to me...

Related

Sql Server how to find values in different tables that have different suffix

I'm struggling to find a value that might be in different tables but using UNION is a pain as there are a lot of tables.
[Different table that contains the suffixes from the TestTable_]
| ID | Name|
| -------- | -----------|
| 1 | TestTable1 |
| 2 | TestTable2 |
| 3 | TestTable3 |
| 4 | TestTable4 |
TestTable1 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------- |
| 1 | goose | withFeather? |featherID |
| 2 | rooster| withoutFeather?|shinyfeatherID |
| 3 | rooster| age | 20 |
TestTable2 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------------------|
| 1 | brazilian_goose | withFeather? |featherID |
| 2 | annoying_rooster | withoutFeather?|shinyfeatherID |
| 3 | annoying_rooster | no_legs? |dead |
TestTable3 content:
| id | Name | q1 | a1 |
| -------- | ---------------------------------------- |
| 1 | goose | withFeather? |featherID |
| 2 | rooster| withoutFeather?|shinyfeatherID |
| 3 | rooster| age | 15 |
Common columns: q1 and a1
Is there a way to parse through all of them to lookup for a specific value without using UNION because some of them might have different columns?
Something like: check if "q1='age'" exists in all those tables (from 1 to 50)
Select q1,*
from (something)
where q1 exists in (TestTable_*)... or something like that.
If not possible, not a problem.
You could use dynamic SQL but something I do in situations like this where I have a list of tables that I want to quickly perform the same actions on is to either use a spreadsheet to paste the list of tables into and type a query into the cell with something like #table then use the substitute function to replace it.
Alternative I just paste the list into SSMS and use SHIFT+ALT+ArrowKey to select the column and start typing stuff out.
So here is my list of tables
Then I use that key combo. As you can see my cursor has now selected all those rows.
Now I can start typing and all rows selected will get the input.
Then I just go to the other side of the table names and repeat the action
It's not a perfect solution but it's quick a quick and dirty way of doing something repetitive quickly.
If you want to find all the tables with that column name you can use information schema.
Select table_name from INFORMATION_SCHEMA.COLUMNS where COLUMN_NAME = 'q1'
Given the type of solution you are after I can offer a method that I've had to use on legacy systems.
You can query sys.columns for the name of the column(s) you need to find in N tables and join using object_id to sys.tables where type='U'. This will give you a list of table names.
From this list you can then build a working query for each table, and depending on your requirements (is this ad-hoc?) either just manually execute it yourself of build a procedure that will do it for you using sp_executesql
Eg
select t.name, c.name
into #workingtable
from sys.columns c
join sys.tables t on t.object_id=c.object_id
where c.name in .....
psudocode:
begin loop while rows exist in #working table
select top 1 row from #workingtable
set #sql=your query specific to that table and column(s)
exec(#sql) / sp_executesql / try/catch as necessary
delete row from working table
end loop
Hopefully that give ideas at least for how you might implement your requirements.

How to get records from a table where some field's value is in camel-case

I have a table like this,
+----+-----------+
| Id | Value |
+----+-----------+
| 1 | ABC_DEF |
| 31 | AcdEmc |
| 44 | AbcDef |
| 2 | BAA_CC_CD |
| 55 | C_D_EE |
+----+-----------+
I need a query to get the records which Value is only in camelcase (ex: AcdEmc, AbcDef etc. not ABC_DEF).
Please note that this table has only these two types of string values.
You can use UPPER() for this
select * from your_table
where upper(value) <> value COLLATE Latin1_General_CS_AS
If your default collation is case-insensitive you can force a case-sensitive collation in your where clause. Otherwise you can remove that part from your query.
Based on the sample data, the following will work. I think the issue we're dealing with is checking whether the string contains underscores.
SELECT * FROM [Foo]
WHERE Value NOT LIKE '%[_]%';
See Fiddle
UPDATE: Corrected error. I forgot '_' meant "any character".

Stored Procedures - Updating and Inserting

I'm new to using stored procedures, what is the best way to update and insert using stored procedures. I have two tables and I can match them by a distinct ID, I want to update if the ID exists in both my load table and my destination table, and I want to insert if the item does not exist in my destination table. Just an example template would be very helpful, thanks!
If I understood well, you want to select values in one table and insert them in other table. If the id exists in the second table, you need to update the row. If I'm not wrong you need something like this:
mysql> select * from table_1;
+----+-----------+-----------+
| id | name | last_name |
+----+-----------+-----------+
| 1 | fagace | acero |
| 2 | ratangelo | saleh |
| 3 | hectorino | josefino |
+----+-----------+-----------+
3 rows in set (0.00 sec)
mysql> select * from table_2;
+----+-----------+-----------+
| id | name | last_name |
+----+-----------+-----------+
| 1 | fagace | acero |
| 2 | ratangelo | saleh |
+----+-----------+-----------+
2 rows in set (0.00 sec)
mysql> insert into table_2 select t1.id,t1.name,t1.last_name from table_1 t1 on duplicate key update name=t1.name, last_name=t1.last_name;
Query OK, 1 row affected (0.00 sec)
Records: 3 Duplicates: 0 Warnings: 0
mysql> select * from table_2;
+----+-----------+-----------+
| id | name | last_name |
+----+-----------+-----------+
| 1 | fagace | acero |
| 2 | ratangelo | saleh |
| 3 | hectorino | josefino |
+----+-----------+-----------+
3 rows in set (0.00 sec)
mysql>
You should look up the SQL MERGE statement.
It allows you to perform UPSERT's - i.e. INSERT if a key value does not already exist, UPDATE if the key does exist.
http://technet.microsoft.com/en-us/library/bb510625.aspx
However, your requirement to check for a key value in 2 places before you perform an update does make it more complex. I haven't tried this but I would think a VIEW or a CTE could be used to establish if the ID exists in both your tables & then base the MERGE on the CTE/VIEW.
But definitely start by looking at MERGE!

Google Cloud SQL - "SELECT .. AS .." doesn't change the column name

I'm trying to retrieve some columns value from a google cloud sql database, and I want to rename the output column as follows:
select id as tot from mytable
the query result I get is this:
id
value1
value2
value3
...
as you can see the column name is not changed as I wanted.. I also tried
select id as 'tot' from mytable
and (in fact this works, but obviously every row value is set to 'id' instead of the real row value)
select 'id' as 'tot' from mytable
the table schema I'm testing on is as simple as possible:
create table mytable(id varchar(10))
Has anyone encountered this problem before? Am I missing something or doing something wrong?
Thanks in advance for any help, best regards
This works as expected using the command line tool and looks like a bug in the web ui.
Here's what I got from the command line tool use (google_sql.sh)
sql> insert into mytable values('1'), ('2'), ('3');
3 row(s) affected.
sql> select * from mytable;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
+----+
3 rows in set (0.10 sec)
sql> select id as 'tot' from mytable
-> ;
+-----+
| tot |
+-----+
| 1 |
| 2 |
| 3 |
+-----+
3 rows in set (0.09 sec)
sql> select 'id' as 'tot' from mytable
-> ;
+-----+
| tot |
+-----+
| id |
| id |
| id |
+-----+
3 rows in set (0.09 sec)
I just logged a bug for this: https://code.google.com/p/googlecloudsql/issues/detail?id=60

A subquery that should be independent is not. Why?

I have a table files with files and a table reades with read accesses to these files. In the table reades there is a column file_id where refers to the respective column in files.
Now I would like to list all files which have not been accessed and tried this:
SELECT * FROM files WHERE file_id NOT IN (SELECT file_id FROM reades)
This is terribly slow. The reason is that mySQL thinks that the subquery is dependent on the query:
+----+--------------------+--------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+--------------------+--------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | PRIMARY | files | ALL | NULL | NULL | NULL | NULL | 1053 | 100.00 | Using where |
| 2 | DEPENDENT SUBQUERY | reades | ALL | NULL | NULL | NULL | NULL | 3242 | 100.00 | Using where |
+----+--------------------+--------+------+---------------+------+---------+------+------+----------+-------------+
But why? The subquery is completely independent and more or less just meant to return a list of ids.
(To be precise: Each file_id can appear multiple times in reades, of course, as there can be arbitrarily many read operations for each file.)
Try replacing the subquery with a join:
SELECT *
FROM files f
LEFT OUTER JOIN reades r on r.file_id = f.file_id
WHERE r.file_id IS NULL
Here's a link to an article about this problem. The writer of that article wrote a stored procedure to force MySQL to evaluate subqueries as independant. I doubt that's necessary in this case though.
i've seen this before. it's a bug in mysql. try this:
SELECT * FROM files WHERE file_id NOT IN (SELECT * FROM (SELECT file_id FROM reades))
there bug report is here: http://bugs.mysql.com/bug.php?id=25926
Try:
SELECT * FROM files WHERE file_id NOT IN (SELECT reades.file_id FROM reades)
That is: if it's coming up as dependent, perhaps that's because of ambiguity in what file_id refers to, so let's try fully qualifying it.
If that doesn't work, just do:
SELECT files.*
FROM files
LEFT JOIN reades
USING (file_id)
WHERE reades.file_id IS NULL
Does MySQL support EXISTS in the same way that MSSQL would?
If so, you could rewrite the query as
SELECT * FROM files as f WHERE file_id NOT EXISTS (SELECT 1 FROM reades r WHERE r.file_id = f.file_id)
Using IN is horribly inefficient as it runs that subquery for each row in the parent query.
Looking at this page I found two possible solutions which both work. Just for completeness I add one of those, similar to the answers with JOINs shown above, but it is fast even without using foreign keys:
SELECT * FROM files AS f
INNER JOIN (SELECT DISTINCT file_id FROM reades) AS r
ON f.file_id = r.file_id
This solves the problem, but still this does not answer my question :)
EDIT: If I interpret the EXPLAIN output correctly, this is fast, because the interpreter generates a temporary index:
+----+-------------+------------+--------+---------------+---------+---------+-----------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+---------+---------+-----------+------+--------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 843 | |
| 1 | PRIMARY | f | eq_ref | PRIMARY | PRIMARY | 4 | r.file_id | 1 | |
| 2 | DERIVED | reades | range | NULL | file_id | 5 | NULL | 811 | Using index for group-by |
+----+-------------+------------+--------+---------------+---------+---------+-----------+------+--------------------------+
IN-subqueries are in MySQL 5.5 and earlier converted to EXIST subqueries. The given query will be converted to the following query:
SELECT * FROM files
WHERE NOT EXISTS (SELECT 1 FROM reades WHERE reades.filed_id = files.file_id)
As you see, the subquery is actually dependent.
MySQL 5.6 may choose to materialize the subquery. That is, first, run the inner query and store the result in a temporary table (removing duplicates). Then, it can use a join-like operation between the outer table (i.e., files) and the temporary table to find the rows with no match. This way of executing the query will probably be more optimal if reades.file_id is not indexed.
However, if reades.file_id is indexed, the traditional IN-to-EXISTS execution strategy is actually pretty efficient. In that case, I would not expect any significant performance improvement from converting the query into a join as suggested in other answers. MySQL 5.6 optimizer makes a cost-based choice between materialization and IN-to-EXISTS execution.