Perl DBI SQL SERVER CONNECTIVITY ISSUES - sql-server

Very new to Perl. I am having issues trying to get DBI to communicate to a SQL server 2008 DB.
I get the following error when I try and connect to SQL Servereveb when I try to use ODBC or directly.
I am new to Perl, can someone please assist...thanks
install_driver(MSSQL) failed: Can't locate object method "set_sql" via package "Class::DBI::MSSQL" at C:/Perl/lib/DBD/MSSQL.pm line 79. Compilation failed in require at (eval 19)C:/Perl/site/lib/DBI.pm:744 line 3.
use strict;
use warnings;
use diagnostics;
use Class::DBI::Loader;
use DBI;
use File::Glob ':glob';
my $DBUserName = "*******";
my $DBPassword = "*******";
my $DBName = "dbi:MSSQL:uat-dbserver1";
my $dbh = "";
my $sqlStatement = "";
my $sqlCmd = "";
my #EasySetTableNames = ();
$dbh = DBI->connect( $DBName, $DBUserName, $DBPassword,
{ PrintError => 0, AutoCommit => 0})
|| die "Database connection creation failed: $DBI::errstr\n";
$sqlStatement = "SELECT * from tableA ";
$sqlCmd = $dbh->prepare($sqlStatement);
$sqlCmd->execute();
#EasySetTableNames = #{$dbh->selectcol_arrayref($sqlStatement)};
print "hi";
and via ODBC
#!/usr/bin/perl -w
use strict;
use DBI;
# Replace datasource_name with the name of your data source.
# Replace database_username and database_password
# with the SQL Server database username and password.
my $data_source = "dbi:MSSQL:test";
my $user = "test";
my $password = "test";
# Connect to the data source and get a handle for that connection.
my $dbh = DBI->connect($data_source, $user, $password)
or die "Can't connect to $data_source: $DBI::errstr";
# This query generates a result set with one record in it.
my $sql = "SELECT 1 AS test_col";
# Prepare the statement.
my $sth = $dbh->prepare($sql)
or die "Can't prepare statement: $DBI::errstr";
# Execute the statement.
$sth->execute();
# Print the column name.
print "$sth->{NAME}->[0]\n";
# Fetch and display the result set value.
while ( my #row = $sth->fetchrow_array ) {
print "#row\n";
}
# Disconnect the database from the database handle.
$dbh->disconnect;
Any help you can provide would be so appreciated.

I usually use the ODBC driver from within the dbi and this is how I would usually hit sql server (2008 r2)
#!/export/appl/pkgs/perl/5.8.4-fiq/bin/perl
#!/usr/bin/perl
#!/bin/sh
use strict;
use DBI;
use Time::localtime;
use Data::Dumper;
my $dsn = 'DBI:ODBC:Driver={SQL Server}';
my $host = 'xxx\yyy';
my $database = 'testing';
my $user = 'user';
my $auth = 'password';
my $dbh = DBI->connect("$dsn;Server=$host;Database=$database", $user, $auth) or die "Database connection not made: $DBI::errstr";
my $sql = "EXECUTE database.schema.sproc";
my $stmt = $dbh->prepare($sql);
$stmt->execute();
$stmt->finish();
$dbh->disconnect;

I was able to connect to SQL Server using OLE32, here is an example of the code..."Cursor type changed" error on Perl OLE32 MSSQL dateadd function results

Related

How to remove encryption from all objects in SQL Server?

I have more than a hundred encrypted procedures and functions that I want to decrypt (I am trying a bacpac file export but it fails due to procedures being encrypted). I tried using dbforge sql decryptor decryption wizard for in place alter but I get the error:
Definition is invalid. Can't find CREATE keyword.
When I try to see the DDL script of a stored procedure(using dbforge sql decryptor), I get the error:
A definition for the object dbo.pt_blocks cannot be shown because it is encrypted by a third party tool
I can not find a resolution to this. Are there any solutions or other tools available for this?
Edit: I found this resource which mentions
take the source code and issue an ALTER command without the encryption option. Just take the source code and remove the WITH ENCRYPTION
How could I achieve this?
EDIT: I have enabled remote DAC. How can I decrypt everything? The accepted answer from this question has a broken link.
Edit: The problem has been solved by uninstalling a third party tool which was creating encrypted procedures.
Below is a PowerShell example that creates a script file of all encrypted objects, gleaned from Paul White's The Internals of WITH ENCRYPTION article. Change the data source and initial catalog in the 2 connection strings to the desired server and database as well as script file path.
A DAC connection is used to retrieve values from system tables so sysadmin server role membership is required. If run remotely, the SQL Server remote admin connections option must be enabled and TCP port 1434 allowed through the firewall.
The script can be run from the PowerShell ISE or from a command prompt after customization. Example command-line invocation, assuming script was saved to file "Decrypt-Objects.ps1".
powershell -ExecutionPolicy RemoteSigned -File C:\PowershellScripts\Decrypt-Objects.ps1
PowerShell script:
# PowerShell implementation of T-SQL code from https://sqlperformance.com/2016/05/sql-performance/the-internals-of-with-encryption
Function Get-DecryptedString($pwd, $data) {
$key = [System.Array]::CreateInstance([int], 256)
$box = [System.Array]::CreateInstance([int], 256)
$cipher = [System.Array]::CreateInstance([byte], $data.Length)
for ($i = 0; $i -lt 256; ++$i) {
$key[$i] = $pwd[$i % $pwd.Length]
$box[$i] = $i
}
for ($j = $i = 0; $i -lt 256; ++$i) {
$j = ($j + $box[$i] + $key[$i]) % 256
$tmp = $box[$i]
$box[$i] = $box[$j]
$box[$j] = $tmp
}
for ($a = $j = $i = 0; $i -lt $data.Length; ++$i) {
++$a
$a %= 256
$j += $box[$a]
$j %= 256
$tmp = $box[$a]
$box[$a] = $box[$j]
$box[$j] = $tmp
$k = $box[(($box[$a] + $box[$j]) % 256)]
$cipher[$i] = ($data[$i] -bxor $k)
}
$decryptedString = [System.Text.Encoding]::Unicode.GetString($cipher)
return $decryptedString
}
Function Get-ClearObjectText($connectionString, $objectName) {
$getRc4KeyQuery = #"
DECLARE
#objectid integer = OBJECT_ID(#ObjectName),
#family_guid binary(16),
#objid binary(4),
#subobjid binary(2);
-- Find the database family GUID
SELECT #family_guid = CONVERT(binary(16), DRS.family_guid)
FROM sys.database_recovery_status AS DRS
WHERE DRS.database_id = DB_ID();
-- Convert object ID to little-endian binary(4)
SET #objid = CONVERT(binary(4), REVERSE(CONVERT(binary(4), #objectid)));
SELECT
-- Read the encrypted value
#imageval = SOV.imageval,
-- Get the subobjid and convert to little-endian binary
#subobjid = CONVERT(binary(2), REVERSE(CONVERT(binary(2), SOV.subobjid)))
FROM sys.sysobjvalues AS SOV
WHERE
SOV.[objid] = #objectid
AND SOV.valclass = 1;
-- Compute the RC4 initialization key
SELECT #RC4key = HASHBYTES('SHA1', #family_guid + #objid + #subobjid);
"#
$connection = New-Object System.Data.SqlClient.SqlConnection($dacConnectionString)
$connection.Open()
$command = New-Object System.Data.SqlClient.SqlCommand($getRc4KeyQuery, $connection)
($command.Parameters.Add("#ObjectName", [System.Data.SqlDbType]::NVarChar, 261)).Value = $objectName
($command.Parameters.Add("#imageval", [System.Data.SqlDbType]::VarBinary, -1)).Direction = [System.Data.ParameterDirection]::Output
($command.Parameters.Add("#RC4key", [System.Data.SqlDbType]::Binary, 20)).Direction = [System.Data.ParameterDirection]::Output
[void]$command.ExecuteNonQuery()
$imageval = $command.Parameters["#imageval"].Value
$RC4key = $command.Parameters["#RC4key"].Value
$connection.Close()
$decryptedString = Get-DecryptedString -pwd $RC4key -data $imageval
Return $decryptedString
}
# ############
# ### MAIN ###
# ############
# DAC connection string for decryption
$dacConnectionString = "Data Source=admin:YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI"
# normal connection string for encrypted object list
$connectionString = "Data Source=YourServer;Initial Catalog=YourDatabase;Integrated Security=SSPI"
# target file path for clear encrypted objects DDL
$scriptFilePath = "C:\Scripts\EncryptedObjects.sql"
[void](New-Item -Path "C:\Scripts\EncryptedObjects.sql" -ItemType file -Force) # create directory (if needed) and empty script file
$EncryptedObjectQuery = #"
SELECT
QUOTENAME(OBJECT_SCHEMA_NAME(object_id)) + '.' + QUOTENAME(name) AS QualifiedObjectName
FROM sys.objects
WHERE OBJECTPROPERTY(object_id, 'IsEncrypted') = 1;
"#
try {
$connection = New-Object System.Data.SqlClient.SqlConnection($connectionString)
$command = New-Object System.Data.SqlClient.SqlCommand($EncryptedObjectQuery, $connection)
$connection.Open()
$reader = $command.ExecuteReader()
while ($reader.Read()) {
$createObjectScript = Get-ClearObjectText -connectionString $dacConnectionString -objectName $reader["QualifiedObjectName"]
$createObjectScript | Out-File -FilePath $scriptFilePath -Append
"GO" | Out-File -FilePath $scriptFilePath -Append
}
$connection.Close()
}
catch {
throw
}

Database connection script crashes after 4 successful connections

I need to query a group of SAP sybase databases for some information and print that as a comma spearated list. So I figure I write a perl script that connects to any of those databases via DBI module. Here is what I came up with.
my $user = "someuser";
my $passwd = "somepassword";
my #sids=(filled with DB identifiers);
my $output="";
my $size;
my $version;
my $id;
my $dsn;
my $dbh;
my $sid;
my #row;
my $sth1;
my $sth2;
foreach $sid (#sids) {
print $sid."\n";
$dsn = "dbi:Sybase:server=$sid;charset=iso_1;tdsLevel=CS_TDS_50";
print $dsn."\n";
$dbh = DBI->connect($dsn, $user, $passwd,{ PrintError => 0,RaiseError => 0, AutoCommit => 1, syb_enable_utf8 => 1});
print "DBI OK\n" if defined ($dbh);
$sth1 = $dbh->prepare('select SUM(size) from master..sysusages WHERE dbid = 4 AND segmap = 3');
$sth2 = $dbh->prepare('select ##version');
$sth1->execute;
while (#row = $sth1->fetchrow) {
$size = $row[0];
}
$size = $size * 16 / 1024;
$sth1->finish;
$sth2->execute;
while (#row = $sth2->fetchrow) {
$version = $row[0];
}
$sth2->finish;
$output = $sid.",".$size.",".$version;
$dbh->disconnect;
print $output."\n";
}
When I execute this, it crashes after 4th iteration, because the connection handle is not set. So the connection of the fifth DB does not work anymore.
Can't call method "prepare" on an undefined value at ./check_sybasedbs.pl line 36.
Line 36 is the preparation of statement 1.
I tried putting sleep commands at various positions. I also tried to explicitly clean up the variables that are reused via undef. Now I am out of ideas and would really appreciate your input.
Your code could be written as sample below (please see if ... else ... block for $dbh)
use strict;
use warnings;
use feature 'say';
use DBI;
my($user, $passwd) = qw/someuser somepassword/;
my #sids = qw/server1 server2 ... server#/;
foreach my $sid (#sids) {
my $dsn = "dbi:Sybase:server=$sid;charset=iso_1;tdsLevel=CS_TDS_50";
say "DSN: $dsn";
my $dbh = DBI->connect($dsn, $user, $passwd, { PrintError => 1,
RaiseError => 1,
AutoCommit => 1,
syb_enable_utf8 => 1
}
);
if( not defined ($dbh) ) {
say "WARNING: Could not connect to $dsn";
} else {
say "INFO: DB connection established";
my($size,$version);
my $query = 'SELECT
SUM(size)
FROM
master..sysusages
WHERE
dbid = 4
AND
segmap = 3
';
my $sth = $dbh->prepare($query);
$sth->execute;
while (#row = $sth->fetchrow) {
$size = $row[0];
}
$sth->finish;
$query = 'select ##version';
$sth = $dbh->prepare($query);
$sth->execute;
while (#row = $sth->fetchrow) {
$version = $row[0];
}
$sth->finish;
$dbh->disconnect;
$size = $size * 16 / 1024;
say "SID: $sid, SIZE: $size, VERSION: $version";
}
}
NOTE: use strict; use warnings; helps to avoid many pitfalls, use diagnostics; helps to identify a problem in difficult cases
NOTE: $sth->fetchrow_hashref allows address hash element by name, no need to count index of array as in case $sth->fetch_rowarray
in my naiv thinking I hid some lines of code that I was convinced could not be the reason for this misbehaviour. As it turns out, it was. So the reason for my problem was a simple logical error, that caused the password, that was used after a connect to a certain DB to be wrong.

Using stored procedures with cakephp 3.x

I am trying to use a SQL Server stored procedure with cakephp 3.x, but I get a database error.
This is my controller:
use Cake\Datasource\ConnectionManager;
if($this->request->is('post')){
$data = $this->request->getData();
$param1 = $data['playId'];
$param2 = $data['cardboard'];
if(is_numeric($param1) && is_numeric($param2)){
$param1 = $data['playId'];
$param2 = $data['cardboard'];
$conn = ConnectionManager::get('ssql');
$requested = $conn->query(
'call searchPrem(?, ?)',
[$param1, $param2]
)->fetchAll('assoc');
//$exec = debug($requested);
}
echo json_encode( $requested );
}
I get this SQL error:
Error: SQLSTATE[42000]: [Microsoft][ODBC Driver 13 for SQL Server][SQL Server]Incorrect syntax near '#P1'.
How can I execute a stored procedure and retrieve the result data?
I found the solution:
$conn = ConnectionManager::get('ssql');
$sql = $conn->execute("yourfunction #id = $playId, #type = $type")->fetchAll('assoc');
In Cake 2.x I used solution like below:
if ($connection = $this->getDataSource()->connection) {
$statement = oci_parse($connection, "DECLARE x number; BEGIN :x := searchPrem(" . $var1 . ", " . $var2 . "); END;");
oci_bind_by_name($statement, ':x', $result, 10);
if (oci_execute($statement)) {
// Success
}
}
This example works with Oracle dialect. You should modify to Cake 3.x and Your database dialect.

Specify insert into list with different sql source and dest connection in Powershell

I have this powershell script that would work if my DEST table ONLY had the columns listed in the select from my SOURCE server, but the DEST table has more. I haven't been able to find anything that gives examples on how to specify the columns from my dest table I want to insert into. Note that the SourceServer and DestServer are not linked servers.
Param (
#[parameter(Mandatory = $true)]
[string] $SrcServer = "SourceServer",
[parameter(Mandatory = $true)]
[string] $SrcDatabase = "SourceDb",
#[parameter(Mandatory = $true)]
[string] $SrcTable = "stage.InternalNotes",
#[parameter(Mandatory = $true)]
[string] $DestServer = "DestServer",
#[parameter(Mandatory = $true)]
[string] $DestDatabase = "DestDb",
[parameter(Mandatory = $true)]
[string] $DestTable = "dbo.InternalNotes",
)
Function ConnectionString([string] $ServerName, [string] $DbName)
{
"Data Source=$ServerName;Initial Catalog=$DbName;Integrated Security=True;User ID=$UID;Password=$PWD;"
}
$SrcConnStr = ConnectionString $SrcServer $SrcDatabase
$SrcConn = New-Object System.Data.SqlClient.SQLConnection($SrcConnStr)
$CmdText = "SELECT
ino.UserId
,ino.StoreId
,ino.PostedById
,ino.DatePosted
,ino.NoteSubject
,ino.NoteText
,ino.NoteType
,ino.Classify
,ino.CreatedBy
,ino.CreatedUtc
,IsReadOnly = 0
FROM
stage.InternalNotes AS ino
"
$SqlCommand = New-Object system.Data.SqlClient.SqlCommand($CmdText, $SrcConn)
$SrcConn.Open()
[System.Data.SqlClient.SqlDataReader] $SqlReader = $SqlCommand.ExecuteReader()
Try
{
$DestConnStr = ConnectionString $DestServer $DestDatabase
$bulkCopy = New-Object Data.SqlClient.SqlBulkCopy($DestConnStr, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity)
$bulkCopy.DestinationTableName = $DestTable
$bulkCopy.WriteToServer($sqlReader)
}
Catch [System.Exception]
{
$ex = $_.Exception
Write-Host $ex.Message
}
Finally
{
Write-Host "Table $SrcTable in $SrcDatabase database on $SrcServer has been copied to table $DestTable in $DestDatabase database on $DestServer"
$SqlReader.close()
$SrcConn.Close()
$SrcConn.Dispose()
$bulkCopy.Close()
}
Essentially, I need to be able to do this:
INSERT INTO dbo.InternalNotes --DEST Server table
(
userID
,StoreID
,PostedByID
,DatePosted
,NoteSubject
,NoteText
,NoteType
,Classify
,CreatedBy
,CreatedDateUTC
,IsReadOnly
)
SELECT
ino.UserId
,ino.StoreId
,ino.PostedById
,ino.DatePosted
,ino.NoteSubject
,ino.NoteText
,ino.NoteType
,ino.Classify
,ino.CreatedBy
,ino.CreatedUtc
,IsReadOnly = 0
FROM
stage.InternalNotes AS ino --SOURCE Server table
Edits after getting everything to work based on the accepted answer:
For some reason it didn't like the line:
$bulkCopy = New-Object -TypeName Data.SqlClient.SqlBulkCopy -ArgumentList $DestSqlConnection, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity, $DestSqlTransaction;
It gave the error:
Cannot convert argument "1", with value:
"[System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity", for
"SqlBulkCopy" to type "System.Data.SqlClient.SqlBulkCopyOptions":
"Cannot convert value
"[System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity" to type
"System.Data.SqlClient.SqlBulkCopyOptions". Error: "Unable to match
the identifier name
[System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity to a valid
enumerator name. Specify one of the following enumerator names and try
again: Default, KeepIdentity, CheckConstraints, TableLock, KeepNulls,
FireTriggers, UseInternalTransaction,
AllowEncryptedValueModifications""
So Instead I changed it to this, and everything worked:
$bulkCopy = New-Object Data.SqlClient.SqlBulkCopy($DestSqlConnection, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity,$DestSqlTransaction)
To do manual column mapping, you need to populate SqlBulkCopy.ColumnMappings. If you don't specify the mapping, then as far as I know SqlBulkCopy will assume the first column in the select list or DataRow goes into the first ordinal column of the destination table.
For example:
$bulkCopy.DestinationTableName = $DestTable;
$bulkCopy.ColumnMappings.Add('sourceColumn1','destinationColumn1');
$bulkCopy.ColumnMappings.Add('sourceColumn2','destinationColumn2');
$bulkCopy.ColumnMappings.Add('sourceColumn3','destinationColumn3');
$bulkCopy.ColumnMappings.Add('sourceColumn4','destinationColumn4');
$bulkCopy.ColumnMappings.Add('sourceColumn5','destinationColumn5');
However, there's a number of other issues with your script.
Your connection string authentication section is nonsense:
`Integrated Security=True; User ID=$UID; Password=$PWD;`
Integrated Security=True says, "Use passthrough Windows authentication with currently logged on user." User ID=$UID; Password=$PWD; says, "Use SQL authentication with the specified username and password." You can't do both.
You should specify only one or the other.
$SqlCommand = New-Object system.Data.SqlClient.SqlCommand($CmdText, $SrcConn)
[...]
$bulkCopy = New-Object Data.SqlClient.SqlBulkCopy($DestConnStr, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity)
I may be wrong, but I'm pretty sure you're trying to pass two variables as one argument here. Just like with your ConnectionString function, I don't think you don't want parentheses here. In any case it's syntactically confusing. Do this instead:
$SqlCommand = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList $CmdText, $SrcConn
[...]
$bulkCopy = New-Object -TypeName Data.SqlClient.SqlBulkCopy -ArgumentList $DestConnStr, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity
Speaking of that last one, I have another issue with it. SqlBulkCopy is powerful, but you really have to hold it's hand. By default, SqlBulkCopy doesn't run with any transaction benefits. That means that if it errors in the middle, well, too bad, your data has been partially updated. You can enable internal transactions, but then only the most recent batch of the inserts will be rolled back. You really need to manage your own transaction to get an all-or-nothing result.
So you'll end up with something like this:
Try {
$DestConnStr = ConnectionString $DestServer $DestDatabase
# We have to open the connection before we can create the transaction
$DestSqlConnection = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $DestConnStr;
$DestSqlConnection.Open();
$DestSqlTransaction = $DestSqlConnection.BeginTransaction();
$bulkCopy = New-Object -TypeName Data.SqlClient.SqlBulkCopy -ArgumentList $DestSqlConnection, [System.Data.SqlClient.SqlBulkCopyOptions]::KeepIdentity, $DestSqlTransaction;
$bulkCopy.DestinationTableName = $DestTable
$bulkCopy.ColumnMappings.Add('sourceColumn1','destinationColumn1');
$bulkCopy.ColumnMappings.Add('sourceColumn2','destinationColumn2');
$bulkCopy.ColumnMappings.Add('sourceColumn3','destinationColumn3');
$bulkCopy.ColumnMappings.Add('sourceColumn4','destinationColumn4');
$bulkCopy.ColumnMappings.Add('sourceColumn5','destinationColumn5');
Try {
$bulkCopy.WriteToServer($sqlReader)
# Commit on success
$DestSqlTransaction.Commit();
}
Catch {
# Rollback on error
$DestSqlTransaction.Rollback();
# Rethrow the error to the outer catch block
throw ($_);
}
}
Catch [System.Exception] {
$ex = $_.Exception
Write-Host $ex.Message
}
Finally {
[...]
}
I'd probably rewrite the above more because I don't like nested try blocks, but for a quick and dirty rewrite this will work. I don't think you'll run into any problems with distributed transaction problems doing this, but I may be wrong. I tend to use SSIS or linked servers when I need this sort of data pump.

How to fetch and display an array using PDO?

I understand there are MANY ways to do all of this, but trying to do it the best way.
I have created the db parameters, dns, dbh, sth, sql and generally quite happy with the result up to ... well ... the result part.
<?php
// db parameters
$dbhost = "localhost";
$dbname = "x";
$dbuser = "y";
$dbpass = "z";
// driver invocation (dsn is short for data source name)
$dsn = "mysql:host=$dbhost;dbname=$dbname";
// create db object (dbh is short for database handle)
$dbh = new PDO($dsn, $dbuser, $dbpass);
// execution of database query (sth is short for statement handle)
$sql = "SELECT * FROM a_aif_remaining";
$sth = $dbh->prepare($sql);
$sth->execute();
NOT SURE WHAT TO PUT BELOW.... (A) or (B)
I just want to present a simple array of the data. One row from the table per line.
Option A
echo $_POST['fieldname1'];
echo $_POST['fieldname2'];
echo $_POST['fieldname3'];
Option B
while ($rows = $sth->fetch(PDO::FETCH_ASSOC)) {
echo $row[fieldname1],'<br>';
}
AND I AM CONFIDENT WITH THE ENDING
$dbh = NULL;
?>
Any advise would be GREATLY appreciated.
UPDATED CODE: (Produces nothing on the page)
<?php
// db parameters
$dbhost = "localhost";
$dbname = "theaudit_db1";
$dbuser = "theaudit_user";
$dbpass = "audit1999";
$dsn = "mysql:host=$dbhost;dbname=$dbname"; // driver invocation (dsn is short for Data Source Name)
try {
$dbh = new PDO($dsn, $dbuser, $dbpass); // connect to new db object (dbh is short for Database Handle)
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // set the PDO error mode to enable exceptions
$dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); // set the PDO emulate prepares to false
// execute query to database (sth is short for Statement Handle)
$sql = "SELECT * FROM a_aif_remaining";
$sth = $dbh->prepare($sql);
$sth->execute();
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
$dbh = NULL;
}
catch(PDOException $e)
{
echo $e->getMessage();
}
?>
Though I can't get what's the connection between A anb B, I can answer the
I just want to present a simple array of the data. One row from the table per line.
question.
$sql = "SELECT * FROM a_aif_remaining";
$sth = $dbh->prepare($sql);
$sth->execute();
$data = $sth->fetchAll(PDO::FETCH_ASSOC);
where $data is a sought-for array.
The problem with your updated code is simple - you arent echo'ing your data out. You need to add something like..
foreach($data as $arKey=>$dataRow){
foreach($dataRow as $arKey=>$rowField){
echo $rowField.','; //concat with a ',' to give csv like output
}
echo '<br>'; //to get to next line for each row (may want to trim the last ','
}
I am also confused by the reference to $_POST. It is true both are associate arrays but that does not mean that the $_POST option is viable - the data would only be available in the $_POST if you put it there (eg $_POST = $data) which would be pointless. Or if you had posted the data from somewhere else. Neither seem to fit what you are asking so I would forget about the $_POST and just figure out how you access your multi dimensional $data array. There is endless tut's on this subject. Try using
var_dump($data)
to see whats inside that should help you visualise what is going on.
NOTE: in option B you are not correctly concatenating or referencing your array it should be:
while ($rows = $sth->fetch(PDO::FETCH_ASSOC)) {
echo $rows[fieldname1].'<br>'; //$row doesnt exist its $rows and you use . to concat not ,
}
Ah yes and probably better to use unset rather than setting $dbh to equal null
unset($dbh);

Resources