title: I am trying to synchronise a Sage Line 50 Access database with Mysql via ODBC
body: <p>I am trying to source the structure and data from a sage line 50 database but am having trouble with my update/create script. </p>
  
  <p>Basically, I am writing a tool so that the local intranet site can display data sourced from sage to normal employees without using up a sage login (orders due in/stock levels etc). I am having trouble with this because it seems that the Sage50 database was developed by total morons. There are no Unique keys in this database, or, more accurately, very very few. The structure is really old school you can find the structure on pastebin <a href="http://pastebin.com/k30Ny77i" rel="nofollow">HERE</a> (bit too big for here). You'll notice that there are some tables with 300+ columns, which I think is a bit stupid. However, I have to work with this and so I need a solution. </p>
  
  <p>There are a few problems syncing that I have encountered. Primarily it's the fact ODBC can't limit statements to 1 row so I can check data type, and secondly, with there being no IDs, I can't check if it's a duplicate when doing the insert. At the moment, this is what I have:</p>
  
  <pre><code>$rConn = odbc_connect("SageLine50", "user", "password");
  
  if ($rConn == 0) {
      die('Unable to connect to the Sage Line 50 V12 ODBC datasource.');
  }
  
  $result = odbc_tables($rConn);
  
  $tables = array();
  
  while (odbc_fetch_row($result)){
      if(odbc_result($result,"TABLE_TYPE")=="TABLE") {
          $tables[odbc_result($result,"TABLE_NAME")] = array();
      }
  }
  </code></pre>
  
  <p>This produces the first level of the list you see on pastebin. </p>
  
  <p>A foreach statement is then run to produce the next level with the columns within the table</p>
  
  <pre><code>foreach($tables as $k=&gt; $v) {
      $query = "SELECT * FROM ".$k;
      $rRes = odbc_exec($rConn,$query);
      $rFields = odbc_num_fields ($rRes);
      $i = 1;
      while($i &lt;= $rFields) {
          $tables[$k][] = odbc_field_name($rRes, $i);
          $i++;   
      }
      CreateTableandRows($k,$tables[$k]);
  }
  </code></pre>
  
  <p>At the moment, I then have a bodged together function to create each table (not that I like the way it does it).</p>
  
  <p>Because I can't automatically grab back one row (or a few rows), to check the type of data with get_type() to then automatically set the row type, it means the only way I can figure out to do this is to set the row type as text and then change them retrospectively based upon a Mysql query. </p>
  
  <p>Here is the function that's called for the table creation after the foreach above. </p>
  
  <pre><code>function CreateTableandRows($table,$rows) {
      $db = array(
          "host" =&gt; '10.0.0.200',
          "user" =&gt; 'user',
          "pass" =&gt; 'password',
          "table" =&gt; 'ccl_sagedata'
      );
  
  $DB = new Database($db);
  
      $LocSQL = "CREATE TABLE IF NOT EXISTS `".$table."` (
              `id` int(11) unsigned NOT NULL auto_increment,
              PRIMARY KEY  (`id`),";  
  
      foreach($rows as $k=&gt;$v) {
              $LocSQL .= "
              ".$v." TEXT NOT NULL default '',";
      }
  
      $LocSQL = rtrim($LocSQL, ',');
  
      $LocSQL .= "
              ) ENGINE=MyISAM  DEFAULT CHARSET=utf8";
  
      echo '&lt;pre&gt;'.$LocSQL.'&lt;/pre&gt;';
  
      $DB-&gt;query($LocSQL);
  
  }
  </code></pre>
  
  <p>I then need/want a function that takes each table at a time and synchronizes the data to the ccl_sagedata database. However, it needs to make sure it's not inserting duplicates, i.e. this script will be run to sync the sage database at the start or end of each day and without ID numbers INSERT REPLACE won't work. I am obviously implementing auto inc primary ID's for each new table in the ccl_sagedata db. But I needs to be able to reference something static in each table that I can identify through ODBC (I hope that makes sense). In my current function, it has to call the mysql database for each row on the sage database and see if there is a matching row.</p>
  
  <pre><code>function InsertDataFromSage($ODBCTable) {
      $rConn = odbc_connect("SageLine50", "user", "pass");
      $query = "SELECT * FROM ".$ODBCTable;
      $rRes = odbc_exec($rConn,$query);
      $rFields = odbc_num_fields ($rRes);
      while( $row = odbc_fetch_array($rRes) ) {
          $result[] = $row;
      } 
      $DB = new Database($db);
      foreach($result as $k =&gt; $v) {
          $CHECKEXISTS = "SELECT * FROM ".$ODBCTable." WHERE";
          $DB-&gt;query($CHECKEXISTS);
          // HERE WOULD BE A PART THAT PUTS DATA INTO THE DATABASE IF IT DOESN'T ALREADY EXIST
      }
  }
  </code></pre>
  
  <p>The only other thing I can think to note is that the 'new Database' class is simply just a functionalised standard mysqli database class. It's not something I'm having problems with. </p>
  
  <p>So to re-cap. </p>
  
  <ol>
  <li>I am trying to create a synchronization script that creates (if not exists) tables within a mysql database and then imports/syncs the data.</li>
  <li>ODBC Can't limit the output so I can't figure out the data types in the columns automatically (can't do it manually because it's a massive db with 80+ tables</li>
  <li>I can't figure out how to stop the script creating duplicates because there are no IDs in the sage source database. </li>
  <li>For those of you not in the UK, Sage is a useless accounting package that runs on water and coal.</li>
  <li>The Sage database only provides data, it doesn't allow you to input data outside of csv files in the actual program. </li>
  </ol>