Can you reorder SQLite table columns via a query?
I would prefer a query method, but if that is not possible is there any other way?
Yes, you control the order of columns by the order you name them in the query. Both these queries return the same rows, but the columns are in a different order.
select first_column_name, second_column_name
from mytable;
select second_column_name, first_column_name
from mytable;
If you want it to appear that the columns in the base table have been permanently changed, you can use a view.
create view mytable_reordered
select second_column_name, first_column_name
from mytable;
If you wanted to make that change transparent to application programs, you'd first rename the table, then create the view, giving it the old name of the table. Finally, you'd jump through whatever hoops your dbms requires in order to make that view updatable. In SQLite, I think that means writing code to implement some INSTEAD OF triggers.
Related
I have a table that is actually a ranking list. I want to give user a chance to rearrange that top the way he wants, ergo, allow him to move the rows in that table. Should I create a separate column that would hold the place, or can it be done using embedded order in table?
The documentation says:
If a SELECT statement that returns more than one row does not have an ORDER BY clause, the order in which the rows are returned is undefined.
(This is true for all SQL databases.)
So you cannot rely on the order that the rows happen to be stored in; you have to use some value in some table column.
I have a Customers table which contains the salesRepEmployeeNumber which is in the Employees table.
How do I do something like
SELECT *
FROM Customers
JOIN Employees
ON Customers.salesRepEmployeeNumber = Employees.employeeNumber
with icCube ETL ?
As pointed in another answer, you can add a table based in an SQL statement that would do the job. In case your original datasource is not able to do a join :
We've not yet an join transformation, added this in our todo list. On the meantime, what you can do is.
Create an Union Table with your two tables. This will create a new table with the columns of both tables. Put the small one, first as we're going to cache it later on.
Create a Javascript view, you might need to activate Javascript in your icCube.xml configuration. In this one you can cache the first table and use a bit of js to do the join. You can trigger the table change on a field being empty. Don't forget to put 'Table Row Ordering' to Keep Table Order.
hope it helps
No need to use the ETL.
With the designer, add a table with the + sign in the menu above DataSource. The next panel gives you the choice between reading data from an existing table or an sql query.
I need to manipulate some data in SQLite, it should be simple but trying to figure it out how to do exactly this has frustrated me.
It's just a join, one table called "routes" has a column "stop_id". I need to take another table called "stops" which also has a "stop_id" column and everywhere that they match, add all the additional columns from "stops" to the "routes" table (added columns are "stop_name" "stop_lat" "stop_lon" and "master_station"). "stop_id" is the primary key in the stops table. I need to join the tables and not keep them relational because after I do that I will be changing the rows by hand with new information. I am using Firefox SQLite Manager if that matters.
A join can be done with JOIN:
SELECT * FROM routes JOIN stops USING (stop_id)
However, the result of a join cannot be changed directly; the UPDATE statement works only on actual tables.
To change values that come from the routes or stops tables, you have to update those tables by using their respective primary keys to look up the records.
I am using a global application user account to access database A. This user account does not have permissions to modify database A's schema (ie, create tables, modify tables, etc). This user also has access to database B, but only views. I need to run SQL to feed data from a view in database B into a table in database A.
In a perfect world, I would be able to use this SQL:
create database_a.mytable as (select * from database_b) with no data
However, the user can't create tables in database A. If I could get the DDL of the select statement then I could log in under my personal account (which doesn't have any access to database B) and run the DDL in database A to create the table.
The only other option is to manually write the SQL, but I don't want to do that, especially since this view I am wanting to copy has many columns of varying data types and sizes.
Edit: I may be getting closer. I just experimented with this:
show (select * from database_b.myview)
However, it generated the DLL of every single table that is used in the view itself, as well as the definition for the view. This doesn't really help me since I just want the schema of the select statement itself. In other words, I need what would be generated if I were to use the create table as statement mentioned above.
Edit for Rob: Perhaps "DDL" was the wrong term to use. Using show view db.myview just shows the definition of the view, not the schema it represents. In my above example of create table as, I show how you can create a table that mimics the schema of a result set returned in a select. It generates a DDL on the back end for creating a table and then executes that DDL to actually create the table. You can then say show table db.newtable and see the new table's DDL. I want to get that DDL directly from a select statement so that I can copy it, log out of the app account, into my personal account, and then execute the DDL to create the table.
This is only to save me the headache of having to type out the DDL manually by hand to save time and reduce typing errors, especially since the source view has so many columns. That said, I think hitting up the DBA or writing some snazzy stored procedure to do dynamic stuff would be a bit over the top for my needs. I think there has to be a way to get the DDL for creating a table schema directly from a select statement.
Generate DDL Statements for objects:
SHOW TABLE {DatabaseB}.{Table1};
SHOW VIEW {DatabaseB}.{View1};
Breakdown of columns in a view:
HELP VIEW {DatabaseB}.{View1};
However, without the ability to create the object in the target database DatabaseA your don't have much leverage. Obviously, if the object already existed INSERT INTO SELECT ... FROM DatabaseB.Table1 or MERGE INTO would be options that you already explored.
Alternative Solution
Would it be possible to have a stored procedure created that dynamically created the table based on the view name that is provided? The global application account would simply need privilege to execute the procedure. Generally the user creating the stored procedure would need the permissions to perform the actions contained within the stored procedure. (You have some additional flexibility with this in Teradata 13.10.)
There are some caveats with this approach. You are attempting to materialize views that could reference anywhere from hundreds to billions of records. These aren't simple 1:1 views that are put on top of the target tables. Trying to determine the required space in the target database to materialize the view will be difficult. Performance can and will vary depending on the complexity of the view and the data volumes. This will not be a fast-path or data block optimized operation.
As a DBA, I would be concerned with this approach being taken on by a global application account without fully understanding the intent. I trust you have an open line of communication with the DBA(s) involved for supporting this system. I'm sure there are reasons for your madness that can't be disclosed here.
Possible Solution - VOLATILE TABLE
Unless the implicit privilege for CREATE TABLE has been revoked from the global application account this solution should work.
Volatile tables do not require perm space. There table definitions persist for the duration of the session and any data inserted into them relies on the spool space of the user who instantiated it.
CREATE VOLATILE TABLE {Global Application UserID}.{TableA_Copy} AS
(
SELECT *
FROM {DatabaseB}.{TableA}
)
WITH NO DATA
NO PRIMARY INDEX
ON COMMIT PRESERVE ROWS;
SHOW TABLE {Global Application UserID}.{TableA_Copy};
I opted to use a Teradata 13.10 feature called NO PRIMARY INDEX. By default, CREATE TABLE AS will take the first column of the SELECT statement and make it the PRIMARY INDEX of the table. This could lead to skewing and perm space issues in your testing depending on the data demographics. You can specify an explicit PRIMARY INDEX on your own as you understand the underlying data. (See the DDL manuals for details on the syntax if you're uncertain.)
The use of ON COMMIT PRESERVE ROWS for the intent of this example is probably extraneous. But in reality if you popped any data into that table for testing this clause would be beneficial in Teradata mode as the data would otherwise be lost immediately after the CREATE TABLE or any other data manipulation was performed against the volatile table.
There is the table OLD and a similar one, NEW. I want to insert in the existing process that fills the table OLD a trigger event that for each new inserted row, this event will insert the newly inserted row to table NEW, as well. Inside the body of trigger, i need to include the query BELOW which aggregates values of OLD before inserted in NEW:
insert into NEW
select (select a.id,a.name,a.address,b.jitter,a.packet,a.compo,b.rtd,a.dur from OLD a,
select address,packet,compo, avg(jitter) as jitter, avg(rtd) as rtd from OLD
group by address,packet,compo ) b
where a.address=b.address and a.packet=b.packet and a.compo=b.compo;
can you correct any possible mistakes or suggest other trigger syntax on the statement below?
CREATE OR REPLACE TRIGGER insertion
after update on OLD
for each row
begin
MY select query above
end;
In a for each row trigger you cannot query the table itself. You will get a mutating table error message if you do.
I recommend only to use triggers for the most basic functionality such as handing out ID numbers and very basic checks.
If you do use triggers for more complex tasks you may very easily end up with a system that's very hard to debug and maintain because of all kinds of actions that appear out of knowhere.
Look at this question for another approach: getting rid of Insert trigger
Oracle Streams might also be a good solution. In the apply handler, you can include your own custom PL/SQL code. This procedure will be called after the COMMIT, so you can avoid mutating table errors.
However, Streams requires a large amount of setup to make it work. It might be overkill for what you are doing.