Sort MySQL column in alphanumeric order - sql

How can I sort into MySQL in AlphaNumeric order;
Suppose I have a table with data like this.
Name + ID
AA | 10
AE | 2
AD | 1
When I sort column ID the result is
1
10
2
But when I add + 0 in select statement like this for column id
SELECT * FROM tableName ORDER BY columnName + 0;
1
2
10
But the result for column Name is this
AA
AE
AD
I already refer to this link but it doesn't work for me.
Alphanumeric Order By in Mysql
Note: All column type is varchar and I cannot predict what data will be inserted.
I know my problem is simple but still I can't get the result I want.
Also I cannot use Java to sort the result because I use LIMIT on it.
I'll appreciate any help.Thanks
Additional Info: (Sample Table to be sorted base on Name and ID)
The header1 is the Name which set to another table and same with header2 w/c is ID
CREATE TABLE IF NOT EXISTS `sort` (
`header1` varchar(200) DEFAULT NULL,
`header2` varchar(200) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `sort` (`header1`, `header2`) VALUES
('AA', '10'),
('AE', '2'),
('AD', '1'),
('AD', '1'),
('AF', 'a'),
('AF', 'a1'),
('1', 'a1');

Change your field's datatype to a numerical data type instead of a Character type.
The plus zero must work because it is converting the data to a number.

It seems like its not sorting because it shows the order how I inserted the data.
Now it's clear! The problem is your misunderstanding how tables work. There's no defined order for a table. That's it. Whenever you do a SELECT without an ORDER BY, the DB is free to return the columns in any order it likes. And there's nothing you could do about it.
Normally, the rows get returned in an order determined by the primary key. Tf there's none, the insertion order gets used, unless there are deletions. After deletions, the DB puts the new records somewhere to fill the gaps. However, this is no guaranteed behavior, when you switch to another version or whatever, it may change.
Never rely on the order of rows in a table. Always use ORDER BY or a VIEW containing ORDER BY if the order matters.

Related

Does Oracle allow an SQL INSERT INTO using a SELECT statement for VALUES if the destination table has an GENERATE ALWAYS AS IDENTITY COLUMN

I am trying to insert rows into an Oracle 19c table that we recently added a GENERATED ALWAYS AS IDENTITY column (column name is "ID"). The column should auto-increment and not need to be specified explicitly in an INSERT statement. Typical INSERT statements work - i.e. INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2'). (merely an example). The ID field increments when typical INSERT is executed. But the query below, that was working before the addition of the IDENTITY COLUMN, is now not working and returning the error: ORA-00947: not enough values.
The field counts are identical with the exception of not including the new ID IDENTITY field, which I am expecting to auto-increment. Is this statement not allowed with an IDENTITY column?
Is the INSERT INTO statement, using a SELECT from another table, not allowing this and producing the error?
INSERT INTO T.AUDIT
(SELECT r.IDENTIFIER, r.SERIAL, r.NODE, r.NODEALIAS, r.MANAGER, r.AGENT, r.ALERTGROUP,
r.ALERTKEY, r.SEVERITY, r.SUMMARY, r.LASTMODIFIED, r.FIRSTOCCURRENCE, r.LASTOCCURRENCE,
r.POLL, r.TYPE, r.TALLY, r.CLASS, r.LOCATION, r.OWNERUID, r.OWNERGID, r.ACKNOWLEDGED,
r.EVENTID, r.DELETEDAT, r.ORIGINALSEVERITY, r.CATEGORY, r.SITEID, r.SITENAME, r.DURATION,
r.ACTIVECLEARCHANGE, r.NETWORK, r.EXTENDEDATTR, r.SERVERNAME, r.SERVERSERIAL, r.PROBESUBSECONDID
FROM R.STATUS r
JOIN
(SELECT SERVERSERIAL, MAX(LASTOCCURRENCE) as maxlast
FROM T.AUDIT
GROUP BY SERVERSERIAL) gla
ON r.SERVERSERIAL = gla.SERVERSERIAL
WHERE (r.LASTOCCURRENCE > SYSDATE - (1/1440)*5 AND gla.maxlast < r.LASTOCCURRENCE)
) )
Thanks for any help.
Yes, it does; your example insert
INSERT INTO table_name (field1,field2) VALUES ('f1', 'f2')
would also work as
INSERT INTO table_name (field1,field2) SELECT 'f1', 'f2' FROM DUAL
db<>fiddle demo
Your problematic real insert statement is not specifying the target column list, so when it used to work it was relying on the columns in the table (and their data types) matching the results of the query. (This is similar to relying on select *, and potentially problematic for some of the same reasons.)
Your query selects 34 values, so your table had 34 columns. You have now added a 35th column to the table, your new ID column. You know that you don't want to insert directly into that column, but in general Oracle doesn't, at least at the point it's comparing the query with the table columns. The table has 35 columns, so as you haven't said otherwise as part of the statement, it is expecting 35 values in the select list.
There's no way for Oracle to know which of the 35 columns you're skipping. Arguably it could guess based on the identity column, but that would be more work and inconsistent, and it's not unreasonable for it to insist you do the work to make sure it's right. It's expecting 35 values, it sees 34, so it throws an error saying there are not enough values - which is true.
Your question sort of implies you think Oracle might be doing something special to prevent the insert ... select ... syntax if there is an identity column, but in facts it's the opposite - it isn't doing anything special, and it's reporting the column/value count mismatch as it usually would.
So, you have to list the columns you are populating - you can't automatically skip one. So you statement needs to be:
INSERT INTO T.AUDIT (IDENTIFIER, SERIAL, NODE, ..., PROBESUBSECONDID)
SELECT r.IDENTIFIER, r.SERIAL, r.NODE, ..., r.PROBESUBSECONDID
FROM ...
using the actual column names of course if they differ from the query column names.
If you can't change that insert statement then you could make the ID column invisible; but then you would have to specify it explicitly in queries, as select * won't see it - but then you shouldn't rely on * anyway.
db<>fiddle

If an Order By clause is specified, are identity values consistent? [duplicate]

When inserting multiple rows in a table, is there any guarantee that they go in in the order I specify? For instance, take the following:
DECLARE #blah TABLE
(
ID INT IDENTITY(1, 1),
Name VARCHAR(100) NOT NULL
);
INSERT INTO #blah (Name)
VALUES('Timmy'),
('Jonny'),
('Sally');
SELECT * FROM #blah
Is there any guarantee that Sally will have a higher primary key than Timmy?
The very similar question was asked before.
You can specify an ORDER BY in the INSERT.
If you do that, the order in which the IDENTITY values are generated is guaranteed to match the specified ORDER BY in the INSERT.
Using your example:
DECLARE #blah TABLE
(
ID INT IDENTITY(1, 1) NOT NULL,
Name VARCHAR(100) NOT NULL
);
INSERT INTO #blah (Name)
SELECT T.Name
FROM
(
VALUES
('Timmy'),
('Jonny'),
('Sally')
) AS T(Name)
ORDER BY T.Name;
SELECT
T.ID
,T.Name
FROM #blah AS T
ORDER BY T.ID;
The result is:
+----+-------+
| ID | Name |
+----+-------+
| 1 | Jonny |
| 2 | Sally |
| 3 | Timmy |
+----+-------+
That is, Name have been sorted and IDs have been generated according to this order. It is guaranteed that Jonny will have the lowest ID, Timmy will have the highest ID, Sally will have ID between them. There may be gaps between the generated ID values, but their relative order is guaranteed.
If you don't specify ORDER BY in INSERT, then resulting IDENTITY IDs can be generated in a different order.
Mind you, there is no guarantee for the actual physical order of rows in the table even with ORDER BY in INSERT, the only guarantee is the generated IDs.
In a question INSERT INTO as SELECT with ORDER BY Umachandar Jayachandran from MS said:
The only guarantee is that the identity values will be generated based
on the ORDER BY clause. But there is no guarantee for the order of
insertion of the rows into the table.
And he gave a link to Ordering guarantees in SQL Server, where Conor Cunningham from SQL Server Engine Team says:
INSERT queries that use SELECT with ORDER BY to populate rows guarantees how identity values are computed but not the order in which
the rows are inserted
There is a link to MS knowledge base article in the comments in that post: The behavior of the IDENTITY function when used with SELECT INTO or INSERT .. SELECT queries that contain an ORDER BY clause, which explains it in more details. It says:
If you want the IDENTITY values to be assigned in a sequential fashion
that follows the ordering in the ORDER BY clause, create a table that
contains a column with the IDENTITY property and then run an INSERT ... SELECT ... ORDER BY query to populate this table.
I would consider this KB article as an official documentation and consider this behaviour guaranteed.
Your best two options are:
Process the rows individually - insert the parent row, get the ID, then insert the children, then insert the next parent row, etc.
Alternatively, assuming that the data has an actual identifier in the real world (for example, email address, SSN, etc.) then you can use that to join back to your parent table when inserting into the child table.

Order by on Two Datetime Fields .If one field is Null How to avoid Sybase from populating it with default datetime

I am using a Select Query to insert data into a Temp Table .In the Select Query I am doing order by on two columns something like this
insert into #temp
Select accnt_no,acct_name, start_date,end_date From table
Order by start_date DESC,end_date DESC
Select * from #temp
Here when there is an entry present in start_date field and an Null entry in the end_date field .During the order by operation Sybase is filling it with an Default date ( jan 1 1900 ) . I dont want that to happen .If the end_date field is Null . The data should be written just as Null .Any suggestion on how to keep it as Null even while fetching the data from the table .
The 1/1/1900 usually comes from trying to cast an empty string into a datetime.
Is your 'date' source column an actual datetime datatype or a string-ish varchar or char?
Sounds like the table definition requires that end_date not be null, and has default values inserted automatically to prevent them. Are you sure there are even nulls when you do a straight select on the table without the confusion of ordering and inserting?
I created a temp table with a nullable datetime column that has a default value.
Defaults are not there to handle nulls per se, they are there to handle missing values on inserts that were not supplied. If I run an insert without a column list (just as you have done) the default value does not apply and a null is still inserted.
I suggest adding the column list to your insert statement. This might prevent the problem (or expose a different problem in having them in the wrong order.)
insert into #temp (accnt_no, accnt_name, start_date, end_date)
select accnt_no,acct_name, start_date,end_date from ...
Here's a query that should help you find the actual defaults on any of the columns if you don't have access to the create script:
select c.name, object_name(cdefault), text
from tempdb..syscolumns c, tempdb..syscomments cm
where c.id = object_id('tempdb..#temp') and cm.id = c.cdefault

Sql timestamp for created/updated dates

In a few logging tables that are frequently written to, I'd like to be able to store a relative order so that I can union between these tables, and get the order that things actually occurred in.
DateTime2's resolution is lacking. Several rows will get the exact same date, so there is no way to tell which happened first.
Because sorting should work across several tables, sorting by Id is out.
Then I started looking at timestamp. This works for updated dates, but it does not work for created dates, because you can only have one timestamp column per table, and it automatically updates.
This is for Microsoft Sql Server 2008.
Any suggestions?
You can simulate it with another column typed as binary(8) (same as rowversion) and defaulting to ##DBTS:
create table TX (
ID int not null,
Updated rowversion not null,
Created binary(8) not null constraint DF_TX_Created DEFAULT (##DBTS)
)
go
insert into TX (ID)
values (1),(2)
go
update TX set ID = 3 where ID = 1
go
insert into TX (ID)
values (4)
go
select * from TX
Result:
ID Updated Created
----------- ------------------ ------------------
3 0x00000000000007D3 0x00000000000007D0
2 0x00000000000007D2 0x00000000000007D0
4 0x00000000000007D4 0x00000000000007D3
Notes:
The Created values will always be equal to the last rowversion value assigned, so they will "lag", in some sense, compared to Updated values.
Also, multiple inserts from a single statement will receive the same Created values, whereas Updated values will always be distinct.

Is there any editable Auto-Increment besdies IDENTITY?

The reason I need this for is that I made a column on my table called display_order, for now it's smallint and the numbers were pre-determined.
However, when I insert a new record with my software I don't know how to get the highest number in that column and add 1, so I thought about the possibility of an auto-incremented column where if I change 8 to 9 it will change everything else accordingly.
Is this possible?
The answer to your question is "No" IDENTITY is the only auto incrementing capability (and these columns are not updatable)
But if this is a display_order field can't you just make it float to allow you to insert items between other items rather than having to shift all other items down to create a gap?
However, when I insert a new record with my software I don't know how to get the highest number in that column and add 1,
Insert MyTable( display_order, .... )
Select (
Select Max(display_order) + 1
From MyTable As T1
), ...
From MyTable
However, I wouldn't recommend this. If display_order is user settable, then I would simply assume relative values. Thus, it wouldn't matter if a user added two values with a display_order = 0. If you really want to go the extra mile and provide the ability to resequence the display_order, you could do it like so:
Update MyTable
Set display_order = Z.NewSeq
From (
Select PKCol
, Row_Number() Over ( Order By display_order ) As NewSeq
From MyTable
) As Z
Join MyTable As T
On T.PKCol = Z.PKCol
Because you only get one IDENTITY column per table, I would probably use a trigger or other mechanism (if there's a centralized insertion stored proc) to default it to one more than the highest number in the table if not provided. This avoids having to SET IDENTITY_INSERT or anything like that.